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);
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();
1193 Type *RetTy = TLI.getCmpLibcallReturnType(Ctx);
1198 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1203 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1207 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1214 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1220 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1222 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1235 const auto [OeqLibcall, OeqPred] =
1237 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1239 const auto [UnoLibcall, UnoPred] =
1241 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1256 const auto [OeqLibcall, OeqPred] =
1261 const auto [UnoLibcall, UnoPred] =
1266 if (NotOeq && NotUno)
1285 const auto [InversedLibcall, InversedPred] =
1287 if (!BuildLibcall(InversedLibcall,
1312 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1314 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1317 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1323 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1328 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1330 switch (
MI.getOpcode()) {
1333 case TargetOpcode::G_MUL:
1334 case TargetOpcode::G_SDIV:
1335 case TargetOpcode::G_UDIV:
1336 case TargetOpcode::G_SREM:
1337 case TargetOpcode::G_UREM:
1338 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1339 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1347 case TargetOpcode::G_FADD:
1348 case TargetOpcode::G_FSUB:
1349 case TargetOpcode::G_FMUL:
1350 case TargetOpcode::G_FDIV:
1351 case TargetOpcode::G_FMA:
1352 case TargetOpcode::G_FPOW:
1353 case TargetOpcode::G_FREM:
1354 case TargetOpcode::G_FCOS:
1355 case TargetOpcode::G_FSIN:
1356 case TargetOpcode::G_FTAN:
1357 case TargetOpcode::G_FACOS:
1358 case TargetOpcode::G_FASIN:
1359 case TargetOpcode::G_FATAN:
1360 case TargetOpcode::G_FATAN2:
1361 case TargetOpcode::G_FCOSH:
1362 case TargetOpcode::G_FSINH:
1363 case TargetOpcode::G_FTANH:
1364 case TargetOpcode::G_FLOG10:
1365 case TargetOpcode::G_FLOG:
1366 case TargetOpcode::G_FLOG2:
1367 case TargetOpcode::G_FEXP:
1368 case TargetOpcode::G_FEXP2:
1369 case TargetOpcode::G_FEXP10:
1370 case TargetOpcode::G_FCEIL:
1371 case TargetOpcode::G_FFLOOR:
1372 case TargetOpcode::G_FMINNUM:
1373 case TargetOpcode::G_FMAXNUM:
1374 case TargetOpcode::G_FMINIMUMNUM:
1375 case TargetOpcode::G_FMAXIMUMNUM:
1376 case TargetOpcode::G_FSQRT:
1377 case TargetOpcode::G_FRINT:
1378 case TargetOpcode::G_FNEARBYINT:
1379 case TargetOpcode::G_INTRINSIC_TRUNC:
1380 case TargetOpcode::G_INTRINSIC_ROUND:
1381 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1382 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1386 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1394 case TargetOpcode::G_FSINCOS: {
1395 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1399 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1404 case TargetOpcode::G_FMODF: {
1405 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1409 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1414 case TargetOpcode::G_LROUND:
1415 case TargetOpcode::G_LLROUND:
1416 case TargetOpcode::G_INTRINSIC_LRINT:
1417 case TargetOpcode::G_INTRINSIC_LLRINT: {
1418 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1422 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1424 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1430 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1433 MI.eraseFromParent();
1436 case TargetOpcode::G_FPOWI:
1437 case TargetOpcode::G_FLDEXP: {
1438 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1442 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1444 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1449 {
MI.getOperand(1).getReg(), HLTy, 0},
1450 {
MI.getOperand(2).getReg(), ITy, 1}};
1451 Args[1].Flags[0].setSExt();
1453 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1458 case TargetOpcode::G_FPEXT:
1459 case TargetOpcode::G_FPTRUNC: {
1462 if (!FromTy || !ToTy)
1469 case TargetOpcode::G_FCMP: {
1473 MI.eraseFromParent();
1476 case TargetOpcode::G_FPTOSI:
1477 case TargetOpcode::G_FPTOUI: {
1481 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1482 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1485 FromTy, LocObserver);
1490 case TargetOpcode::G_SITOFP:
1491 case TargetOpcode::G_UITOFP: {
1492 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1495 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1497 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1504 case TargetOpcode::G_ATOMICRMW_XCHG:
1505 case TargetOpcode::G_ATOMICRMW_ADD:
1506 case TargetOpcode::G_ATOMICRMW_SUB:
1507 case TargetOpcode::G_ATOMICRMW_AND:
1508 case TargetOpcode::G_ATOMICRMW_OR:
1509 case TargetOpcode::G_ATOMICRMW_XOR:
1510 case TargetOpcode::G_ATOMIC_CMPXCHG:
1511 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1517 case TargetOpcode::G_BZERO:
1518 case TargetOpcode::G_MEMCPY:
1519 case TargetOpcode::G_MEMMOVE:
1520 case TargetOpcode::G_MEMSET: {
1525 MI.eraseFromParent();
1528 case TargetOpcode::G_GET_FPENV:
1529 case TargetOpcode::G_GET_FPMODE: {
1535 case TargetOpcode::G_SET_FPENV:
1536 case TargetOpcode::G_SET_FPMODE: {
1542 case TargetOpcode::G_RESET_FPENV:
1543 case TargetOpcode::G_RESET_FPMODE: {
1551 MI.eraseFromParent();
1558 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1561 switch (
MI.getOpcode()) {
1564 case TargetOpcode::G_IMPLICIT_DEF: {
1566 LLT DstTy = MRI.getType(DstReg);
1574 if (SizeOp0 % NarrowSize != 0) {
1579 MI.eraseFromParent();
1583 int NumParts = SizeOp0 / NarrowSize;
1586 for (
int i = 0; i < NumParts; ++i)
1590 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1592 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1593 MI.eraseFromParent();
1596 case TargetOpcode::G_CONSTANT: {
1597 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1598 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1599 unsigned TotalSize = Ty.getSizeInBits();
1601 int NumParts = TotalSize / NarrowSize;
1604 for (
int I = 0;
I != NumParts; ++
I) {
1605 unsigned Offset =
I * NarrowSize;
1612 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1614 if (LeftoverBits != 0) {
1618 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1622 insertParts(
MI.getOperand(0).getReg(),
1623 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1625 MI.eraseFromParent();
1628 case TargetOpcode::G_SEXT:
1629 case TargetOpcode::G_ZEXT:
1630 case TargetOpcode::G_ANYEXT:
1632 case TargetOpcode::G_TRUNC: {
1636 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1638 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1642 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1643 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1644 MI.eraseFromParent();
1647 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1648 case TargetOpcode::G_FREEZE: {
1652 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1657 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1659 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1661 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1665 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1666 MI.eraseFromParent();
1669 case TargetOpcode::G_ADD:
1670 case TargetOpcode::G_SUB:
1671 case TargetOpcode::G_SADDO:
1672 case TargetOpcode::G_SSUBO:
1673 case TargetOpcode::G_SADDE:
1674 case TargetOpcode::G_SSUBE:
1675 case TargetOpcode::G_UADDO:
1676 case TargetOpcode::G_USUBO:
1677 case TargetOpcode::G_UADDE:
1678 case TargetOpcode::G_USUBE:
1680 case TargetOpcode::G_MUL:
1681 case TargetOpcode::G_UMULH:
1683 case TargetOpcode::G_EXTRACT:
1685 case TargetOpcode::G_INSERT:
1687 case TargetOpcode::G_LOAD: {
1689 Register DstReg = LoadMI.getDstReg();
1690 LLT DstTy = MRI.getType(DstReg);
1694 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1695 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1696 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1698 LoadMI.eraseFromParent();
1704 case TargetOpcode::G_ZEXTLOAD:
1705 case TargetOpcode::G_SEXTLOAD:
1706 case TargetOpcode::G_FPEXTLOAD: {
1708 Register DstReg = LoadMI.getDstReg();
1709 Register PtrReg = LoadMI.getPointerReg();
1711 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1712 auto &MMO = LoadMI.getMMO();
1715 if (MemSize == NarrowSize) {
1717 }
else if (MemSize < NarrowSize) {
1718 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1719 }
else if (MemSize > NarrowSize) {
1731 LoadMI.eraseFromParent();
1734 case TargetOpcode::G_STORE: {
1737 Register SrcReg = StoreMI.getValueReg();
1738 LLT SrcTy = MRI.getType(SrcReg);
1739 if (SrcTy.isVector())
1742 int NumParts = SizeOp0 / NarrowSize;
1744 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1745 if (SrcTy.isVector() && LeftoverBits != 0)
1748 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1749 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1751 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1752 StoreMI.eraseFromParent();
1758 case TargetOpcode::G_FPTRUNCSTORE: {
1760 Register SrcReg = StoreMI.getValueReg();
1761 Register PtrReg = StoreMI.getPointerReg();
1763 auto &MMO = StoreMI.getMMO();
1765 if (MemSize > NarrowSize) {
1769 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1770 if (MemSize == NarrowSize) {
1772 }
else if (MemSize < NarrowSize) {
1773 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1777 StoreMI.eraseFromParent();
1780 case TargetOpcode::G_SELECT:
1782 case TargetOpcode::G_AND:
1783 case TargetOpcode::G_OR:
1784 case TargetOpcode::G_XOR: {
1796 case TargetOpcode::G_SHL:
1797 case TargetOpcode::G_LSHR:
1798 case TargetOpcode::G_ASHR:
1800 case TargetOpcode::G_CTLZ:
1801 case TargetOpcode::G_CTLZ_ZERO_POISON:
1802 case TargetOpcode::G_CTTZ:
1803 case TargetOpcode::G_CTTZ_ZERO_POISON:
1804 case TargetOpcode::G_CTLS:
1805 case TargetOpcode::G_CTPOP:
1807 switch (
MI.getOpcode()) {
1808 case TargetOpcode::G_CTLZ:
1809 case TargetOpcode::G_CTLZ_ZERO_POISON:
1811 case TargetOpcode::G_CTTZ:
1812 case TargetOpcode::G_CTTZ_ZERO_POISON:
1814 case TargetOpcode::G_CTPOP:
1816 case TargetOpcode::G_CTLS:
1826 case TargetOpcode::G_INTTOPTR:
1834 case TargetOpcode::G_PTRTOINT:
1842 case TargetOpcode::G_PHI: {
1845 if (SizeOp0 % NarrowSize != 0)
1848 unsigned NumParts = SizeOp0 / NarrowSize;
1852 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1860 for (
unsigned i = 0; i < NumParts; ++i) {
1861 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1863 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1864 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1865 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1868 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1870 MI.eraseFromParent();
1873 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1874 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1878 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1884 case TargetOpcode::G_ICMP: {
1886 LLT SrcTy = MRI.getType(LHS);
1892 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1898 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1899 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1905 LLT ResTy = MRI.getType(Dst);
1910 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1912 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1913 auto LHS = std::get<0>(LHSAndRHS);
1914 auto RHS = std::get<1>(LHSAndRHS);
1915 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1922 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1923 auto LHS = std::get<0>(LHSAndRHS);
1924 auto RHS = std::get<1>(LHSAndRHS);
1925 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1926 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1927 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1928 TargetOpcode::G_ZEXT);
1935 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1936 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1937 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1942 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1946 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1951 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1955 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1958 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1961 LHSPartRegs[
I], RHSPartRegs[
I]);
1962 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1968 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1977 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1981 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1982 RHSLeftoverRegs[
I]);
1984 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1985 RHSLeftoverRegs[
I]);
1988 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1989 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1995 MI.eraseFromParent();
1998 case TargetOpcode::G_FCMP:
2007 case TargetOpcode::G_SEXT_INREG: {
2011 int64_t SizeInBits =
MI.getOperand(2).getImm();
2020 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2021 MO1.
setReg(TruncMIB.getReg(0));
2024 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2036 if (SizeOp0 % NarrowSize != 0)
2038 int NumParts = SizeOp0 / NarrowSize;
2046 for (
int i = 0; i < NumParts; ++i) {
2047 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2062 for (
int i = 0; i < NumParts; ++i) {
2065 PartialExtensionReg = DstRegs.
back();
2067 assert(PartialExtensionReg &&
2068 "Expected to visit partial extension before full");
2069 if (FullExtensionReg) {
2074 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2076 FullExtensionReg = DstRegs.
back();
2081 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2084 PartialExtensionReg = DstRegs.
back();
2090 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2091 MI.eraseFromParent();
2094 case TargetOpcode::G_BSWAP:
2095 case TargetOpcode::G_BITREVERSE: {
2096 if (SizeOp0 % NarrowSize != 0)
2101 unsigned NumParts = SizeOp0 / NarrowSize;
2102 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2105 for (
unsigned i = 0; i < NumParts; ++i) {
2106 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2107 {SrcRegs[NumParts - 1 - i]});
2111 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2114 MI.eraseFromParent();
2117 case TargetOpcode::G_PTR_ADD:
2118 case TargetOpcode::G_PTRMASK: {
2126 case TargetOpcode::G_FPTOUI:
2127 case TargetOpcode::G_FPTOSI:
2128 case TargetOpcode::G_FPTOUI_SAT:
2129 case TargetOpcode::G_FPTOSI_SAT:
2131 case TargetOpcode::G_FPEXT:
2138 case TargetOpcode::G_FLDEXP:
2139 case TargetOpcode::G_STRICT_FLDEXP:
2141 case TargetOpcode::G_VSCALE: {
2143 LLT Ty = MRI.getType(Dst);
2147 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2148 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2149 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2152 MI.eraseFromParent();
2159 LLT Ty = MRI.getType(Val);
2160 if (Ty.isScalar() && !Ty.isFloat())
2167 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2169 if (Ty.isPointer()) {
2170 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2172 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2178 if (Ty.isPointerVector())
2179 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2180 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2184 unsigned OpIdx,
unsigned ExtOpcode) {
2186 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2187 MO.
setReg(ExtB.getReg(0));
2193 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2195 MO.
setReg(ExtB.getReg(0));
2201 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2202 MO.
setReg(ExtB.getReg(0));
2206 unsigned OpIdx,
unsigned TruncOpcode) {
2208 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2210 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2217 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2219 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2224 unsigned OpIdx,
unsigned ExtOpcode) {
2226 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2228 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2237 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2239 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2245 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2255 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2262LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2267 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2268 if (DstTy.isVector())
2273 const int SrcSize = SrcTy.getSizeInBits();
2275 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2277 unsigned NumOps =
MI.getNumOperands();
2278 unsigned NumSrc =
MI.getNumOperands() - 1;
2279 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2281 if (WideSize >= DstSize) {
2285 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2286 const unsigned Offset = (
I - 1) * PartSize;
2299 ResultReg = NextResult;
2302 if (WideSize > DstSize)
2304 else if (DstTy.isPointer())
2306 else if (DstTy != WideTy)
2309 MI.eraseFromParent();
2334 const int GCD = std::gcd(SrcSize, WideSize);
2344 if (GCD == SrcSize) {
2347 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2348 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2354 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2356 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2360 const int PartsPerGCD = WideSize / GCD;
2364 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2366 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2373 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2375 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2376 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2379 MI.eraseFromParent();
2384LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2389 int NumDst =
MI.getNumOperands() - 1;
2390 Register SrcReg =
MI.getOperand(NumDst).getReg();
2391 LLT SrcTy = MRI.getType(SrcReg);
2395 Register Dst0Reg =
MI.getOperand(0).getReg();
2396 LLT DstTy = MRI.getType(Dst0Reg);
2405 dbgs() <<
"Not casting non-integral address space integer\n");
2410 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2418 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2427 SrcTy = MRI.getType(SrcReg);
2431 for (
int I = 1;
I != NumDst; ++
I) {
2432 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2433 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2437 MI.eraseFromParent();
2448 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2452 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2455 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2473 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2478 if (PartsPerRemerge == 1) {
2481 for (
int I = 0;
I != NumUnmerge; ++
I) {
2482 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2484 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2485 int Idx =
I * PartsPerUnmerge + J;
2487 MIB.addDef(
MI.getOperand(Idx).getReg());
2490 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2494 MIB.addUse(Unmerge.getReg(
I));
2497 SmallVector<Register, 16> Parts;
2498 for (
int J = 0; J != NumUnmerge; ++J)
2499 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2502 for (
int I = 0;
I != NumDst; ++
I) {
2503 for (
int J = 0; J < PartsPerRemerge; ++J) {
2504 const int Idx =
I * PartsPerRemerge + J;
2508 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2509 RemergeParts.
clear();
2513 MI.eraseFromParent();
2518LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2520 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2521 unsigned Offset =
MI.getOperand(2).getImm();
2524 if (SrcTy.
isVector() || DstTy.isVector())
2536 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2540 if (DstTy.isPointer())
2547 MI.eraseFromParent();
2552 LLT ShiftTy = SrcTy;
2561 MI.eraseFromParent();
2592LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2594 if (TypeIdx != 0 || WideTy.
isVector())
2604LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2608 std::optional<Register> CarryIn;
2609 switch (
MI.getOpcode()) {
2612 case TargetOpcode::G_SADDO:
2613 Opcode = TargetOpcode::G_ADD;
2614 ExtOpcode = TargetOpcode::G_SEXT;
2616 case TargetOpcode::G_SSUBO:
2617 Opcode = TargetOpcode::G_SUB;
2618 ExtOpcode = TargetOpcode::G_SEXT;
2620 case TargetOpcode::G_UADDO:
2621 Opcode = TargetOpcode::G_ADD;
2622 ExtOpcode = TargetOpcode::G_ZEXT;
2624 case TargetOpcode::G_USUBO:
2625 Opcode = TargetOpcode::G_SUB;
2626 ExtOpcode = TargetOpcode::G_ZEXT;
2628 case TargetOpcode::G_SADDE:
2629 Opcode = TargetOpcode::G_UADDE;
2630 ExtOpcode = TargetOpcode::G_SEXT;
2631 CarryIn =
MI.getOperand(4).getReg();
2633 case TargetOpcode::G_SSUBE:
2634 Opcode = TargetOpcode::G_USUBE;
2635 ExtOpcode = TargetOpcode::G_SEXT;
2636 CarryIn =
MI.getOperand(4).getReg();
2638 case TargetOpcode::G_UADDE:
2639 Opcode = TargetOpcode::G_UADDE;
2640 ExtOpcode = TargetOpcode::G_ZEXT;
2641 CarryIn =
MI.getOperand(4).getReg();
2643 case TargetOpcode::G_USUBE:
2644 Opcode = TargetOpcode::G_USUBE;
2645 ExtOpcode = TargetOpcode::G_ZEXT;
2646 CarryIn =
MI.getOperand(4).getReg();
2662 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2663 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2667 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2669 .buildInstr(Opcode, {WideTy, CarryOutTy},
2670 {LHSExt, RHSExt, *CarryIn})
2673 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2675 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2676 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2677 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2682 MI.eraseFromParent();
2687LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2689 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2690 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2691 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2692 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2693 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2706 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2713 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2717 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2718 {ShiftL, ShiftR},
MI.getFlags());
2723 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2726 MI.eraseFromParent();
2731LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2740 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2742 LLT SrcTy = MRI.getType(
LHS);
2743 LLT OverflowTy = MRI.getType(OriginalOverflow);
2750 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2751 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2752 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2759 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2761 MachineInstrBuilder Mulo;
2762 if (WideMulCanOverflow)
2763 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2764 {LeftOperand, RightOperand});
2766 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2771 MachineInstrBuilder ExtResult;
2778 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2782 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2785 if (WideMulCanOverflow) {
2793 MI.eraseFromParent();
2799 unsigned Opcode =
MI.getOpcode();
2803 case TargetOpcode::G_ATOMICRMW_XCHG:
2804 case TargetOpcode::G_ATOMICRMW_ADD:
2805 case TargetOpcode::G_ATOMICRMW_SUB:
2806 case TargetOpcode::G_ATOMICRMW_AND:
2807 case TargetOpcode::G_ATOMICRMW_OR:
2808 case TargetOpcode::G_ATOMICRMW_XOR:
2809 case TargetOpcode::G_ATOMICRMW_MIN:
2810 case TargetOpcode::G_ATOMICRMW_MAX:
2811 case TargetOpcode::G_ATOMICRMW_UMIN:
2812 case TargetOpcode::G_ATOMICRMW_UMAX:
2813 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2819 case TargetOpcode::G_ATOMIC_CMPXCHG:
2820 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2827 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2837 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2842 case TargetOpcode::G_EXTRACT:
2843 return widenScalarExtract(
MI, TypeIdx, WideTy);
2844 case TargetOpcode::G_INSERT:
2845 return widenScalarInsert(
MI, TypeIdx, WideTy);
2846 case TargetOpcode::G_MERGE_VALUES:
2847 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2848 case TargetOpcode::G_UNMERGE_VALUES:
2849 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2850 case TargetOpcode::G_SADDO:
2851 case TargetOpcode::G_SSUBO:
2852 case TargetOpcode::G_UADDO:
2853 case TargetOpcode::G_USUBO:
2854 case TargetOpcode::G_SADDE:
2855 case TargetOpcode::G_SSUBE:
2856 case TargetOpcode::G_UADDE:
2857 case TargetOpcode::G_USUBE:
2858 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2859 case TargetOpcode::G_UMULO:
2860 case TargetOpcode::G_SMULO:
2861 return widenScalarMulo(
MI, TypeIdx, WideTy);
2862 case TargetOpcode::G_SADDSAT:
2863 case TargetOpcode::G_SSUBSAT:
2864 case TargetOpcode::G_SSHLSAT:
2865 case TargetOpcode::G_UADDSAT:
2866 case TargetOpcode::G_USUBSAT:
2867 case TargetOpcode::G_USHLSAT:
2868 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2869 case TargetOpcode::G_CTTZ:
2870 case TargetOpcode::G_CTTZ_ZERO_POISON:
2871 case TargetOpcode::G_CTLZ:
2872 case TargetOpcode::G_CTLZ_ZERO_POISON:
2873 case TargetOpcode::G_CTLS:
2874 case TargetOpcode::G_CTPOP: {
2887 case TargetOpcode::G_CTTZ:
2888 case TargetOpcode::G_CTTZ_ZERO_POISON:
2889 case TargetOpcode::G_CTLZ_ZERO_POISON:
2890 ExtOpc = TargetOpcode::G_ANYEXT;
2892 case TargetOpcode::G_CTLS:
2893 ExtOpc = TargetOpcode::G_SEXT;
2896 ExtOpc = TargetOpcode::G_ZEXT;
2899 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2900 LLT CurTy = MRI.getType(SrcReg);
2901 unsigned NewOpc = Opcode;
2902 if (NewOpc == TargetOpcode::G_CTTZ) {
2909 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2911 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2917 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2927 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2929 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2934 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2935 Opcode == TargetOpcode::G_CTLZ
2940 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2941 MI.eraseFromParent();
2944 case TargetOpcode::G_BSWAP: {
2948 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2949 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2950 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2953 MI.getOperand(0).setReg(DstExt);
2957 LLT Ty = MRI.getType(DstReg);
2959 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2960 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2966 case TargetOpcode::G_BITREVERSE: {
2970 LLT Ty = MRI.getType(DstReg);
2973 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2975 MI.getOperand(0).setReg(DstExt);
2978 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2979 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2984 case TargetOpcode::G_FREEZE:
2985 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2992 case TargetOpcode::G_ABS:
2999 case TargetOpcode::G_ADD:
3000 case TargetOpcode::G_AND:
3001 case TargetOpcode::G_MUL:
3002 case TargetOpcode::G_OR:
3003 case TargetOpcode::G_XOR:
3004 case TargetOpcode::G_SUB:
3005 case TargetOpcode::G_SHUFFLE_VECTOR:
3021 case TargetOpcode::G_SBFX:
3022 case TargetOpcode::G_UBFX:
3036 case TargetOpcode::G_SHL:
3056 case TargetOpcode::G_ROTR:
3057 case TargetOpcode::G_ROTL:
3066 case TargetOpcode::G_SDIV:
3067 case TargetOpcode::G_SREM:
3068 case TargetOpcode::G_SMIN:
3069 case TargetOpcode::G_SMAX:
3070 case TargetOpcode::G_ABDS:
3078 case TargetOpcode::G_SDIVREM:
3088 case TargetOpcode::G_ASHR:
3089 case TargetOpcode::G_LSHR:
3093 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3094 : TargetOpcode::G_ZEXT;
3107 case TargetOpcode::G_UDIV:
3108 case TargetOpcode::G_UREM:
3109 case TargetOpcode::G_ABDU:
3116 case TargetOpcode::G_UDIVREM:
3125 case TargetOpcode::G_UMIN:
3126 case TargetOpcode::G_UMAX: {
3127 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3129 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3133 ? TargetOpcode::G_SEXT
3134 : TargetOpcode::G_ZEXT;
3144 case TargetOpcode::G_SELECT:
3154 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3161 case TargetOpcode::G_FPEXT:
3169 case TargetOpcode::G_FPTOSI:
3170 case TargetOpcode::G_FPTOUI:
3171 case TargetOpcode::G_INTRINSIC_LRINT:
3172 case TargetOpcode::G_INTRINSIC_LLRINT:
3173 case TargetOpcode::G_IS_FPCLASS:
3183 case TargetOpcode::G_SITOFP:
3193 case TargetOpcode::G_UITOFP:
3203 case TargetOpcode::G_FPTOSI_SAT:
3204 case TargetOpcode::G_FPTOUI_SAT:
3209 LLT Ty = MRI.getType(OldDst);
3210 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3212 MI.getOperand(0).setReg(ExtReg);
3213 uint64_t ShortBits = Ty.getScalarSizeInBits();
3216 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3227 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3228 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3236 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3244 case TargetOpcode::G_LOAD:
3245 case TargetOpcode::G_SEXTLOAD:
3246 case TargetOpcode::G_ZEXTLOAD:
3247 case TargetOpcode::G_FPEXTLOAD:
3253 case TargetOpcode::G_STORE: {
3257 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3258 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3259 if (!Ty.isScalar()) {
3267 MI.setMemRefs(MF, {NewMMO});
3274 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3275 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3281 case TargetOpcode::G_FPTRUNCSTORE:
3288 case TargetOpcode::G_CONSTANT: {
3291 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3292 MRI.getType(
MI.getOperand(0).getReg()));
3293 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3294 ExtOpc == TargetOpcode::G_ANYEXT) &&
3297 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3301 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3307 case TargetOpcode::G_FCONSTANT: {
3313 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3315 MI.eraseFromParent();
3318 case TargetOpcode::G_IMPLICIT_DEF: {
3324 case TargetOpcode::G_BRCOND:
3330 case TargetOpcode::G_FCMP:
3341 case TargetOpcode::G_ICMP:
3346 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3350 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3351 unsigned ExtOpcode =
3355 ? TargetOpcode::G_SEXT
3356 : TargetOpcode::G_ZEXT;
3363 case TargetOpcode::G_PTR_ADD:
3364 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3370 case TargetOpcode::G_PHI: {
3371 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3374 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3386 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3389 LLT VecTy = MRI.getType(VecReg);
3393 TargetOpcode::G_ANYEXT);
3407 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3423 LLT VecTy = MRI.getType(VecReg);
3442 case TargetOpcode::G_FADD:
3443 case TargetOpcode::G_FMUL:
3444 case TargetOpcode::G_FSUB:
3445 case TargetOpcode::G_FMA:
3446 case TargetOpcode::G_FMAD:
3447 case TargetOpcode::G_FNEG:
3448 case TargetOpcode::G_FABS:
3449 case TargetOpcode::G_FCANONICALIZE:
3450 case TargetOpcode::G_FMINNUM:
3451 case TargetOpcode::G_FMAXNUM:
3452 case TargetOpcode::G_FMINNUM_IEEE:
3453 case TargetOpcode::G_FMAXNUM_IEEE:
3454 case TargetOpcode::G_FMINIMUM:
3455 case TargetOpcode::G_FMAXIMUM:
3456 case TargetOpcode::G_FMINIMUMNUM:
3457 case TargetOpcode::G_FMAXIMUMNUM:
3458 case TargetOpcode::G_FDIV:
3459 case TargetOpcode::G_FREM:
3460 case TargetOpcode::G_FCEIL:
3461 case TargetOpcode::G_FFLOOR:
3462 case TargetOpcode::G_FCOS:
3463 case TargetOpcode::G_FSIN:
3464 case TargetOpcode::G_FTAN:
3465 case TargetOpcode::G_FACOS:
3466 case TargetOpcode::G_FASIN:
3467 case TargetOpcode::G_FATAN:
3468 case TargetOpcode::G_FATAN2:
3469 case TargetOpcode::G_FCOSH:
3470 case TargetOpcode::G_FSINH:
3471 case TargetOpcode::G_FTANH:
3472 case TargetOpcode::G_FLOG10:
3473 case TargetOpcode::G_FLOG:
3474 case TargetOpcode::G_FLOG2:
3475 case TargetOpcode::G_FRINT:
3476 case TargetOpcode::G_FNEARBYINT:
3477 case TargetOpcode::G_FSQRT:
3478 case TargetOpcode::G_FEXP:
3479 case TargetOpcode::G_FEXP2:
3480 case TargetOpcode::G_FEXP10:
3481 case TargetOpcode::G_FPOW:
3482 case TargetOpcode::G_INTRINSIC_TRUNC:
3483 case TargetOpcode::G_INTRINSIC_ROUND:
3484 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3488 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3494 case TargetOpcode::G_FMODF: {
3504 case TargetOpcode::G_FPOWI:
3505 case TargetOpcode::G_FLDEXP:
3506 case TargetOpcode::G_STRICT_FLDEXP: {
3508 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3529 case TargetOpcode::G_FFREXP: {
3542 case TargetOpcode::G_LROUND:
3543 case TargetOpcode::G_LLROUND:
3554 case TargetOpcode::G_INTTOPTR:
3562 case TargetOpcode::G_PTRTOINT:
3570 case TargetOpcode::G_BUILD_VECTOR: {
3574 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3580 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3588 case TargetOpcode::G_SEXT_INREG:
3597 case TargetOpcode::G_PTRMASK: {
3605 case TargetOpcode::G_VECREDUCE_ADD: {
3614 case TargetOpcode::G_VECREDUCE_FADD:
3615 case TargetOpcode::G_VECREDUCE_FMUL:
3616 case TargetOpcode::G_VECREDUCE_FMIN:
3617 case TargetOpcode::G_VECREDUCE_FMAX:
3618 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3619 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3624 LLT VecTy = MRI.getType(VecReg);
3631 case TargetOpcode::G_VSCALE: {
3638 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3643 case TargetOpcode::G_SPLAT_VECTOR: {
3652 case TargetOpcode::G_INSERT_SUBVECTOR: {
3660 LLT SubVecTy = MRI.getType(SubVec);
3664 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3665 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3666 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3670 auto SplatZero =
MIRBuilder.buildSplatVector(
3675 MI.eraseFromParent();
3679 case TargetOpcode::G_BITCAST:
3691 if (MRI.getType(Dst) == MRI.getType(Src)) {
3692 Observer.changingAllUsesOfReg(MRI, Dst);
3693 MRI.replaceRegWith(Dst, Src);
3694 Observer.finishedChangingAllUsesOfReg();
3695 MI.eraseFromParent();
3704 auto Unmerge =
B.buildUnmerge(Ty, Src);
3705 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3714 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3728 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3737 MI.eraseFromParent();
3748 MI.eraseFromParent();
3755 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3756 if (SrcTy.isVector()) {
3760 if (DstTy.isVector()) {
3775 unsigned PieceSize =
3791 MI.eraseFromParent();
3796 LLT::vector(SrcEC * (SrcEltSize / PieceSize), PieceTy);
3798 MIRBuilder.buildBitcast(PiecesVecTy, Src).getReg(0);
3800 MI.eraseFromParent();
3807 LLT DstCastTy = DstEltTy;
3808 LLT SrcPartTy = SrcEltTy;
3812 if (NumSrcElt < NumDstElt) {
3823 SrcPartTy = SrcEltTy;
3824 }
else if (NumSrcElt > NumDstElt) {
3836 DstCastTy = DstEltTy;
3841 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3845 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3846 MI.eraseFromParent();
3850 if (DstTy.isVector()) {
3853 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3854 MI.eraseFromParent();
3870 unsigned NewEltSize,
3871 unsigned OldEltSize) {
3872 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3873 LLT IdxTy =
B.getMRI()->getType(Idx);
3876 auto OffsetMask =
B.buildConstant(
3878 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3879 return B.buildShl(IdxTy, OffsetIdx,
3880 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3895 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3899 unsigned OldNumElts = SrcVecTy.getNumElements();
3906 if (NewNumElts > OldNumElts) {
3917 if (NewNumElts % OldNumElts != 0)
3921 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3925 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3928 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3930 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3931 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3932 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3933 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3934 NewOps[
I] = Elt.getReg(0);
3937 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3939 MI.eraseFromParent();
3943 if (NewNumElts < OldNumElts) {
3944 if (NewEltSize % OldEltSize != 0)
3966 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3967 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3970 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3974 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3975 ScaledIdx).getReg(0);
3983 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3985 MI.eraseFromParent();
3999 LLT TargetTy =
B.getMRI()->getType(TargetReg);
4000 LLT InsertTy =
B.getMRI()->getType(InsertReg);
4001 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
4002 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
4005 auto EltMask =
B.buildConstant(
4009 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
4010 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
4013 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
4017 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
4031 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
4032 MI.getFirst4RegLLTs();
4044 if (NewNumElts < OldNumElts) {
4045 if (NewEltSize % OldEltSize != 0)
4054 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4055 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4058 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4062 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4063 ScaledIdx).getReg(0);
4073 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4074 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4078 MI.eraseFromParent();
4108 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4112 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4113 return UnableToLegalize;
4118 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4120 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4129 MI.eraseFromParent();
4147 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4148 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4158 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4159 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4161 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4162 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4164 MI.eraseFromParent();
4190 uint64_t Idx = ES->getIndexImm();
4194 LLT DstTy = MRI.getType(Dst);
4195 LLT SrcTy = MRI.getType(Src);
4201 if (DstTy == CastTy)
4209 if (CastEltSize < DstEltSize)
4212 auto AdjustAmt = CastEltSize / DstEltSize;
4213 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4214 SrcTyMinElts % AdjustAmt != 0)
4219 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4220 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4223 ES->eraseFromParent();
4254 uint64_t Idx = ES->getIndexImm();
4258 LLT DstTy = MRI.getType(Dst);
4259 LLT BigVecTy = MRI.getType(BigVec);
4260 LLT SubVecTy = MRI.getType(SubVec);
4262 if (DstTy == CastTy)
4277 if (CastEltSize < DstEltSize)
4280 auto AdjustAmt = CastEltSize / DstEltSize;
4281 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4282 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4288 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4289 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4291 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4294 ES->eraseFromParent();
4302 LLT DstTy = MRI.getType(DstReg);
4312 if (MemSizeInBits != MemStoreSizeInBits) {
4329 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4333 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4334 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4336 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4339 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4341 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4344 if (DstTy != LoadTy)
4352 if (
MIRBuilder.getDataLayout().isBigEndian())
4370 uint64_t LargeSplitSize, SmallSplitSize;
4375 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4382 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4385 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4396 if (Alignment.value() * 8 > MemSizeInBits &&
4401 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4418 LLT PtrTy = MRI.getType(PtrReg);
4424 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4427 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4428 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4429 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4431 SmallPtr, *SmallMMO);
4433 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4434 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4436 if (AnyExtTy == DstTy)
4437 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4439 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4441 if (IntDstTy == DstTy) {
4448 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4454 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4471 LLT SrcTy = MRI.getType(SrcReg);
4479 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4485 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4487 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4491 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4495 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4510 uint64_t LargeSplitSize, SmallSplitSize;
4517 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4520 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4529 if (SrcTy.isPointer()) {
4534 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4537 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4538 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4541 LLT PtrTy = MRI.getType(PtrReg);
4543 LargeSplitSize / 8);
4544 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4550 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4551 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4560 LLT SrcTy = MRI.getType(SrcReg);
4566 assert(SrcTy.isVector() &&
"Expect a vector store type");
4573 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4577 auto Elt =
MIRBuilder.buildExtractVectorElement(
4578 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4579 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4580 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4586 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4587 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4591 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4602 switch (
MI.getOpcode()) {
4603 case TargetOpcode::G_LOAD: {
4621 case TargetOpcode::G_STORE: {
4637 case TargetOpcode::G_SELECT: {
4641 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4643 dbgs() <<
"bitcast action not implemented for vector select\n");
4654 case TargetOpcode::G_AND:
4655 case TargetOpcode::G_OR:
4656 case TargetOpcode::G_XOR: {
4664 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4666 case TargetOpcode::G_INSERT_VECTOR_ELT:
4668 case TargetOpcode::G_CONCAT_VECTORS:
4670 case TargetOpcode::G_SHUFFLE_VECTOR:
4672 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4674 case TargetOpcode::G_INSERT_SUBVECTOR:
4682void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4691 switch(
MI.getOpcode()) {
4694 case TargetOpcode::G_FCONSTANT:
4696 case TargetOpcode::G_BITCAST:
4698 case TargetOpcode::G_SREM:
4699 case TargetOpcode::G_UREM: {
4700 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4702 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4703 {MI.getOperand(1), MI.getOperand(2)});
4705 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4707 MI.eraseFromParent();
4710 case TargetOpcode::G_SADDO:
4711 case TargetOpcode::G_SSUBO:
4713 case TargetOpcode::G_SADDE:
4715 case TargetOpcode::G_SSUBE:
4717 case TargetOpcode::G_UMULH:
4718 case TargetOpcode::G_SMULH:
4720 case TargetOpcode::G_SMULO:
4721 case TargetOpcode::G_UMULO: {
4724 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4725 LLT Ty = MRI.getType(Res);
4727 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4728 ? TargetOpcode::G_SMULH
4729 : TargetOpcode::G_UMULH;
4733 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4734 MI.removeOperand(1);
4737 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4745 if (Opcode == TargetOpcode::G_SMULH) {
4746 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4747 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4754 case TargetOpcode::G_FNEG: {
4755 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4758 Register CastedSubByReg = SubByReg;
4760 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4761 !SubByRegTy.getScalarType().isInteger()) {
4762 auto BitcastDst = SubByRegTy.changeElementType(
4764 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4770 if (ResTy != TyInt) {
4772 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4775 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4777 MI.eraseFromParent();
4780 case TargetOpcode::G_FSUB:
4781 case TargetOpcode::G_STRICT_FSUB: {
4782 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4783 LLT Ty = MRI.getType(Res);
4788 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4789 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4793 MI.eraseFromParent();
4796 case TargetOpcode::G_FMAD:
4798 case TargetOpcode::G_FFLOOR:
4800 case TargetOpcode::G_LROUND:
4801 case TargetOpcode::G_LLROUND: {
4804 LLT SrcTy = MRI.getType(SrcReg);
4805 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4808 MI.eraseFromParent();
4811 case TargetOpcode::G_INTRINSIC_ROUND:
4813 case TargetOpcode::G_FRINT: {
4816 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4819 case TargetOpcode::G_INTRINSIC_LRINT:
4820 case TargetOpcode::G_INTRINSIC_LLRINT: {
4823 LLT SrcTy = MRI.getType(SrcReg);
4825 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4827 MI.eraseFromParent();
4830 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4831 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4832 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4833 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4834 **
MI.memoperands_begin());
4836 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4837 MI.eraseFromParent();
4840 case TargetOpcode::G_LOAD:
4841 case TargetOpcode::G_SEXTLOAD:
4842 case TargetOpcode::G_ZEXTLOAD:
4844 case TargetOpcode::G_STORE:
4846 case TargetOpcode::G_CTLZ_ZERO_POISON:
4847 case TargetOpcode::G_CTTZ_ZERO_POISON:
4848 case TargetOpcode::G_CTLZ:
4849 case TargetOpcode::G_CTTZ:
4850 case TargetOpcode::G_CTPOP:
4851 case TargetOpcode::G_CTLS:
4854 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4856 Register NewRes = MRI.cloneVirtualRegister(Res);
4863 MI.eraseFromParent();
4867 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4868 const LLT CondTy = MRI.getType(CarryOut);
4869 const LLT Ty = MRI.getType(Res);
4871 Register NewRes = MRI.cloneVirtualRegister(Res);
4874 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4880 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4881 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4888 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4893 MI.eraseFromParent();
4897 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4902 MI.eraseFromParent();
4906 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4907 const LLT CondTy = MRI.getType(BorrowOut);
4908 const LLT Ty = MRI.getType(Res);
4911 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4917 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4918 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4925 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4926 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4928 MI.eraseFromParent();
4968 case G_MERGE_VALUES:
4970 case G_UNMERGE_VALUES:
4972 case TargetOpcode::G_SEXT_INREG: {
4973 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4974 int64_t SizeInBits =
MI.getOperand(2).getImm();
4976 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4977 LLT DstTy = MRI.getType(DstReg);
4978 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4981 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4982 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4983 MI.eraseFromParent();
4986 case G_EXTRACT_VECTOR_ELT:
4987 case G_INSERT_VECTOR_ELT:
4989 case G_SHUFFLE_VECTOR:
4991 case G_VECTOR_COMPRESS:
4993 case G_DYN_STACKALLOC:
4995 case G_INSERT_SUBVECTOR: {
4996 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4997 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
5002 Register Subvector =
MI.getOperand(2).getReg();
5003 auto InsertionPointImm =
MI.getOperand(3).getImm();
5006 LLT DstTy = MRI.getType(Subvector);
5010 bool InsertInLowHalf = InsertionPointImm == 0;
5011 auto Extract =
MIRBuilder.buildExtractSubvector(
5013 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
5015 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
5016 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
5018 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
5019 {LowHalf, HighHalf});
5020 MI.eraseFromParent();
5026 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
5027 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
5033 if (i >= InsertionPointImm &&
5035 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
5043 MI.eraseFromParent();
5047 case G_EXTRACT_SUBVECTOR: {
5050 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5052 LLT SrcTy = MRI.getType(SrcReg);
5053 LLT DstTy = MRI.getType(DstReg);
5055 if (SrcTy.isScalable())
5066 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5067 ExtractionPointImm + i)
5071 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5072 MI.eraseFromParent();
5077 case G_STACKRESTORE:
5087 case G_READ_REGISTER:
5088 case G_WRITE_REGISTER:
5095 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5096 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5102 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5107 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5114 case G_TRUNC_SSAT_S:
5115 case G_TRUNC_USAT_U:
5116 case G_TRUNC_SSAT_U:
5122 bool IsSigned =
MI.getOpcode() == G_ABDS;
5123 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5124 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5125 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5148 case G_MEMCPY_INLINE:
5149 case G_MEMSET_INLINE:
5161 case G_ATOMICRMW_SUB: {
5162 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5163 const LLT ValTy = MRI.getType(Val);
5167 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5168 MI.eraseFromParent();
5196 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5200 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5206 Align StackTypeAlign =
5213 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5214 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5219 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5231 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5234 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5245 "Converting bits to bytes lost precision");
5251 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5252 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5254 if (IdxTy != MRI.getType(Index))
5255 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5260 LLT PtrTy = MRI.getType(VecPtr);
5261 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5269 std::initializer_list<unsigned> NonVecOpIndices) {
5270 if (
MI.getNumMemOperands() != 0)
5278 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5287 if (!Ty.isVector()) {
5293 if (Ty.getNumElements() != NumElts)
5308 assert(Ty.isVector() &&
"Expected vector type");
5310 int NumParts, NumLeftover;
5311 std::tie(NumParts, NumLeftover) =
5314 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5315 for (
int i = 0; i < NumParts; ++i) {
5320 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5329 for (
unsigned i = 0; i <
N; ++i) {
5331 Ops.push_back(
Op.getReg());
5332 else if (
Op.isImm())
5333 Ops.push_back(
Op.getImm());
5334 else if (
Op.isPredicate())
5356 std::initializer_list<unsigned> NonVecOpIndices) {
5358 "Non-compatible opcode or not specified non-vector operands");
5359 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5361 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5362 unsigned NumDefs =
MI.getNumDefs();
5370 for (
unsigned i = 0; i < NumDefs; ++i) {
5371 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5379 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5380 ++UseIdx, ++UseNo) {
5383 MI.getOperand(UseIdx));
5392 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5396 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5398 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5399 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5402 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5403 Uses.push_back(InputOpsPieces[InputNo][i]);
5406 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5407 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5412 for (
unsigned i = 0; i < NumDefs; ++i)
5413 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5415 for (
unsigned i = 0; i < NumDefs; ++i)
5416 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5419 MI.eraseFromParent();
5426 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5428 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5429 unsigned NumDefs =
MI.getNumDefs();
5433 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5438 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5439 UseIdx += 2, ++UseNo) {
5447 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5449 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5450 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5452 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5455 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5456 Phi.addUse(InputOpsPieces[j][i]);
5457 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5467 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5469 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5472 MI.eraseFromParent();
5480 const int NumDst =
MI.getNumOperands() - 1;
5481 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5482 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5483 LLT SrcTy = MRI.getType(SrcReg);
5485 if (TypeIdx != 1 || NarrowTy == DstTy)
5492 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5495 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5509 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5510 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5511 const int PartsPerUnmerge = NumDst / NumUnmerge;
5513 for (
int I = 0;
I != NumUnmerge; ++
I) {
5514 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5516 for (
int J = 0; J != PartsPerUnmerge; ++J)
5517 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5518 MIB.addUse(Unmerge.getReg(
I));
5521 MI.eraseFromParent();
5528 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5532 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5534 if (NarrowTy == SrcTy)
5542 assert(SrcTy.isVector() &&
"Expected vector types");
5544 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5558 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5559 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5560 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5566 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5567 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5568 ++i,
Offset += NumNarrowTyElts) {
5571 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5574 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5575 MI.eraseFromParent();
5579 assert(TypeIdx == 0 &&
"Bad type index");
5580 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5595 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5596 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5598 for (
unsigned i = 0; i < NumParts; ++i) {
5600 for (
unsigned j = 0; j < NumElts; ++j)
5601 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5603 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5606 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5607 MI.eraseFromParent();
5615 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5617 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5619 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5621 InsertVal =
MI.getOperand(2).getReg();
5623 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5624 LLT VecTy = MRI.getType(SrcVec);
5630 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5634 MI.eraseFromParent();
5643 SplitPieces[IdxVal] = InsertVal;
5644 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5646 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5650 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5653 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5654 TargetOpcode::G_ANYEXT);
5658 LLT IdxTy = MRI.getType(Idx);
5659 int64_t PartIdx = IdxVal / NewNumElts;
5661 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5664 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5667 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5668 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5669 VecParts[PartIdx] = InsertPart.getReg(0);
5673 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5675 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5679 MI.eraseFromParent();
5699 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5711 LLT ValTy = MRI.getType(ValReg);
5720 int NumLeftover = -1;
5726 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5728 NumParts = NarrowRegs.
size();
5729 NumLeftover = NarrowLeftoverRegs.
size();
5736 LLT PtrTy = MRI.getType(AddrReg);
5746 auto MMO = LdStMI.
getMMO();
5748 unsigned NumParts,
unsigned Offset) ->
unsigned {
5751 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5753 unsigned ByteOffset =
Offset / 8;
5756 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5763 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5764 ValRegs.push_back(Dst);
5765 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5767 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5776 unsigned HandledOffset =
5777 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5781 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5784 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5785 LeftoverTy, NarrowLeftoverRegs);
5799 switch (
MI.getOpcode()) {
5800 case G_IMPLICIT_DEF:
5816 case G_FCANONICALIZE:
5833 case G_INTRINSIC_LRINT:
5834 case G_INTRINSIC_LLRINT:
5835 case G_INTRINSIC_ROUND:
5836 case G_INTRINSIC_ROUNDEVEN:
5839 case G_INTRINSIC_TRUNC:
5867 case G_FMINNUM_IEEE:
5868 case G_FMAXNUM_IEEE:
5890 case G_CTLZ_ZERO_POISON:
5892 case G_CTTZ_ZERO_POISON:
5909 case G_ADDRSPACE_CAST:
5922 case G_STRICT_FLDEXP:
5924 case G_TRUNC_SSAT_S:
5925 case G_TRUNC_SSAT_U:
5926 case G_TRUNC_USAT_U:
5934 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5939 case G_UNMERGE_VALUES:
5941 case G_BUILD_VECTOR:
5942 assert(TypeIdx == 0 &&
"not a vector type index");
5944 case G_CONCAT_VECTORS:
5948 case G_EXTRACT_SUBVECTOR: {
5950 LLT DstTy = MRI.getType(DstReg);
5952 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5962 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5963 uint64_t RequiredSubvectorIndex =
5967 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5970 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5973 MI.eraseFromParent();
5976 case G_EXTRACT_VECTOR_ELT:
5977 case G_INSERT_VECTOR_ELT:
5986 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5987 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5989 case G_SHUFFLE_VECTOR:
5995 case G_INTRINSIC_FPTRUNC_ROUND:
6005 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
6006 "Not a bitcast operation");
6011 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6013 unsigned NewElemCount =
6016 if (NewElemCount == 1) {
6019 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
6026 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
6035 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
6036 MI.eraseFromParent();
6042 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6046 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6047 MI.getFirst3RegLLTs();
6050 if (DstTy != Src1Ty)
6052 if (DstTy != Src2Ty)
6067 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6083 unsigned InputUsed[2] = {-1U, -1U};
6084 unsigned FirstMaskIdx =
High * NewElts;
6085 bool UseBuildVector =
false;
6086 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6088 int Idx = Mask[FirstMaskIdx + MaskOffset];
6093 if (
Input >= std::size(Inputs)) {
6100 Idx -=
Input * NewElts;
6104 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6105 if (InputUsed[OpNo] ==
Input) {
6108 }
else if (InputUsed[OpNo] == -1U) {
6110 InputUsed[OpNo] =
Input;
6115 if (OpNo >= std::size(InputUsed)) {
6118 UseBuildVector =
true;
6123 Ops.push_back(Idx + OpNo * NewElts);
6126 if (UseBuildVector) {
6131 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6133 int Idx = Mask[FirstMaskIdx + MaskOffset];
6138 if (
Input >= std::size(Inputs)) {
6145 Idx -=
Input * NewElts;
6149 .buildExtractVectorElement(
6150 EltTy, Inputs[
Input],
6156 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6157 }
else if (InputUsed[0] == -1U) {
6159 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6160 }
else if (NewElts == 1) {
6161 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6163 Register Op0 = Inputs[InputUsed[0]];
6167 : Inputs[InputUsed[1]];
6169 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6176 MI.eraseFromParent();
6189 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6195 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6198 const unsigned NumParts =
6200 : SrcTy.getNumElements();
6204 if (DstTy != NarrowTy)
6210 unsigned NumPartsLeft = NumParts;
6211 while (NumPartsLeft > 1) {
6212 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6215 .buildInstr(ScalarOpc, {NarrowTy},
6216 {SplitSrcs[Idx], SplitSrcs[Idx + 1]},
6220 SplitSrcs = PartialResults;
6221 PartialResults.
clear();
6222 NumPartsLeft = SplitSrcs.
size();
6226 MI.eraseFromParent();
6231 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6233 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]},
6237 MI.eraseFromParent();
6241 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6243 .buildInstr(RdxMI.getOpcode(), {DstTy},
6253 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6256 Register Acc = PartialReductions[0];
6257 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6258 if (Part == NumParts - 1) {
6259 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, {Acc, PartialReductions[Part]},
6263 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]},
6268 MI.eraseFromParent();
6274 unsigned int TypeIdx,
6276 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6277 MI.getFirst3RegLLTs();
6278 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6282 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6283 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6284 "Unexpected vecreduce opcode");
6285 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6286 ? TargetOpcode::G_FADD
6287 : TargetOpcode::G_FMUL;
6290 unsigned NumParts = SrcTy.getNumElements();
6293 for (
unsigned i = 0; i < NumParts; i++)
6295 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]},
6300 MI.eraseFromParent();
6307 unsigned ScalarOpc) {
6315 while (SplitSrcs.
size() > 1) {
6317 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6327 SplitSrcs = std::move(PartialRdxs);
6331 MI.getOperand(1).setReg(SplitSrcs[0]);
6338 const LLT HalfTy,
const LLT AmtTy) {
6340 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6341 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6345 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6346 MI.eraseFromParent();
6352 unsigned VTBits = 2 * NVTBits;
6355 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6356 if (Amt.
ugt(VTBits)) {
6358 }
else if (Amt.
ugt(NVTBits)) {
6361 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6362 }
else if (Amt == NVTBits) {
6370 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6373 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6374 if (Amt.
ugt(VTBits)) {
6376 }
else if (Amt.
ugt(NVTBits)) {
6378 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6380 }
else if (Amt == NVTBits) {
6384 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6386 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6388 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6394 if (Amt.
ugt(VTBits)) {
6396 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6397 }
else if (Amt.
ugt(NVTBits)) {
6399 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6401 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6402 }
else if (Amt == NVTBits) {
6405 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6407 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6409 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6411 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6418 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6419 MI.eraseFromParent();
6435 LLT DstTy = MRI.getType(DstReg);
6440 LLT ShiftAmtTy = MRI.getType(Amt);
6442 if (DstEltSize % 2 != 0)
6458 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6469 const unsigned NewBitSize = DstEltSize / 2;
6481 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6483 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6484 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6487 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6488 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6490 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6495 switch (
MI.getOpcode()) {
6496 case TargetOpcode::G_SHL: {
6498 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6500 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6501 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6502 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6505 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6506 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6508 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6510 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6512 ResultRegs[0] =
Lo.getReg(0);
6513 ResultRegs[1] =
Hi.getReg(0);
6516 case TargetOpcode::G_LSHR:
6517 case TargetOpcode::G_ASHR: {
6519 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6521 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6522 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6523 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6527 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6530 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6531 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6533 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6537 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6539 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6541 ResultRegs[0] =
Lo.getReg(0);
6542 ResultRegs[1] =
Hi.getReg(0);
6549 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6550 MI.eraseFromParent();
6559 LLT TargetTy,
LLT ShiftAmtTy) {
6562 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6564 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6565 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6566 const bool NeedsInterWordShift = ShiftBits != 0;
6569 case TargetOpcode::G_SHL: {
6572 if (PartIdx < ShiftWords)
6575 unsigned SrcIdx = PartIdx - ShiftWords;
6576 if (!NeedsInterWordShift)
6577 return SrcParts[SrcIdx];
6582 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6586 return Hi.getReg(0);
6589 case TargetOpcode::G_LSHR: {
6590 unsigned SrcIdx = PartIdx + ShiftWords;
6591 if (SrcIdx >= NumParts)
6593 if (!NeedsInterWordShift)
6594 return SrcParts[SrcIdx];
6598 if (SrcIdx + 1 < NumParts) {
6599 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6603 return Lo.getReg(0);
6606 case TargetOpcode::G_ASHR: {
6608 unsigned SrcIdx = PartIdx + ShiftWords;
6609 if (SrcIdx >= NumParts)
6611 if (!NeedsInterWordShift)
6612 return SrcParts[SrcIdx];
6617 (SrcIdx == NumParts - 1)
6621 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6643 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6644 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6649 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6658 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6659 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6661 auto IsZeroBitShift =
6669 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6670 : TargetOpcode::G_SHL;
6673 auto TargetBitsConst =
6675 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6680 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6685 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6687 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6691 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6704 LLT DstTy = MRI.getType(DstReg);
6708 const unsigned NumParts = DstBits / TargetBits;
6710 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6720 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6721 MI.eraseFromParent();
6726 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6727 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6733 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6737 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6740 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6741 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6745 for (
unsigned I = 0;
I < NumParts; ++
I)
6747 Params, TargetTy, ShiftAmtTy);
6749 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6750 MI.eraseFromParent();
6759 LLT DstTy = MRI.getType(DstReg);
6760 LLT ShiftAmtTy = MRI.getType(AmtReg);
6764 const unsigned NumParts = DstBits / TargetBits;
6766 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6783 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6795 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6796 auto TargetBitsLog2Const =
6797 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6798 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6801 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6803 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6811 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6812 auto TargetBitsMinusOneConst =
6813 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6815 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6816 TargetBitsMinusOneConst)
6819 FillValue = ZeroReg;
6827 for (
unsigned I = 0;
I < NumParts; ++
I) {
6829 Register InBoundsResult = FillValue;
6839 for (
unsigned K = 0;
K < NumParts; ++
K) {
6840 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy,
K);
6842 WordShift, WordShiftKConst);
6854 switch (
MI.getOpcode()) {
6855 case TargetOpcode::G_SHL:
6856 MainSrcIdx = (int)
I - (
int)
K;
6857 CarrySrcIdx = MainSrcIdx - 1;
6859 case TargetOpcode::G_LSHR:
6860 case TargetOpcode::G_ASHR:
6861 MainSrcIdx = (int)
I + (
int)
K;
6862 CarrySrcIdx = MainSrcIdx + 1;
6870 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6871 Register MainOp = SrcParts[MainSrcIdx];
6875 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6876 CarryOp = SrcParts[CarrySrcIdx];
6877 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6878 CarrySrcIdx >= (
int)NumParts)
6879 CarryOp = FillValue;
6885 ResultForK = FillValue;
6891 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6898 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6902 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6903 MI.eraseFromParent();
6910 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6913 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6928 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6933 "getNeutralElementForVecReduce called with invalid opcode!");
6934 case TargetOpcode::G_VECREDUCE_ADD:
6935 case TargetOpcode::G_VECREDUCE_OR:
6936 case TargetOpcode::G_VECREDUCE_XOR:
6937 case TargetOpcode::G_VECREDUCE_UMAX:
6939 case TargetOpcode::G_VECREDUCE_MUL:
6941 case TargetOpcode::G_VECREDUCE_AND:
6942 case TargetOpcode::G_VECREDUCE_UMIN:
6945 case TargetOpcode::G_VECREDUCE_SMAX:
6948 case TargetOpcode::G_VECREDUCE_SMIN:
6951 case TargetOpcode::G_VECREDUCE_FADD:
6953 case TargetOpcode::G_VECREDUCE_FMUL:
6955 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6956 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6957 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6958 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6966 unsigned Opc =
MI.getOpcode();
6968 case TargetOpcode::G_IMPLICIT_DEF:
6969 case TargetOpcode::G_LOAD: {
6977 case TargetOpcode::G_STORE:
6984 case TargetOpcode::G_AND:
6985 case TargetOpcode::G_OR:
6986 case TargetOpcode::G_XOR:
6987 case TargetOpcode::G_ADD:
6988 case TargetOpcode::G_SUB:
6989 case TargetOpcode::G_MUL:
6990 case TargetOpcode::G_FADD:
6991 case TargetOpcode::G_FSUB:
6992 case TargetOpcode::G_FMUL:
6993 case TargetOpcode::G_FDIV:
6994 case TargetOpcode::G_FCOPYSIGN:
6995 case TargetOpcode::G_UADDSAT:
6996 case TargetOpcode::G_USUBSAT:
6997 case TargetOpcode::G_SADDSAT:
6998 case TargetOpcode::G_SSUBSAT:
6999 case TargetOpcode::G_SMIN:
7000 case TargetOpcode::G_SMAX:
7001 case TargetOpcode::G_UMIN:
7002 case TargetOpcode::G_UMAX:
7003 case TargetOpcode::G_FMINNUM:
7004 case TargetOpcode::G_FMAXNUM:
7005 case TargetOpcode::G_FMINNUM_IEEE:
7006 case TargetOpcode::G_FMAXNUM_IEEE:
7007 case TargetOpcode::G_FMINIMUM:
7008 case TargetOpcode::G_FMAXIMUM:
7009 case TargetOpcode::G_FMINIMUMNUM:
7010 case TargetOpcode::G_FMAXIMUMNUM:
7011 case TargetOpcode::G_STRICT_FADD:
7012 case TargetOpcode::G_STRICT_FSUB:
7013 case TargetOpcode::G_STRICT_FMUL: {
7021 case TargetOpcode::G_SHL:
7022 case TargetOpcode::G_ASHR:
7023 case TargetOpcode::G_LSHR: {
7029 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
7035 case TargetOpcode::G_FMA:
7036 case TargetOpcode::G_STRICT_FMA:
7037 case TargetOpcode::G_FSHR:
7038 case TargetOpcode::G_FSHL: {
7047 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
7048 case TargetOpcode::G_EXTRACT:
7055 case TargetOpcode::G_INSERT:
7056 case TargetOpcode::G_INSERT_VECTOR_ELT:
7057 case TargetOpcode::G_FREEZE:
7058 case TargetOpcode::G_FNEG:
7059 case TargetOpcode::G_FABS:
7060 case TargetOpcode::G_FSQRT:
7061 case TargetOpcode::G_FCEIL:
7062 case TargetOpcode::G_FFLOOR:
7063 case TargetOpcode::G_FNEARBYINT:
7064 case TargetOpcode::G_FRINT:
7065 case TargetOpcode::G_INTRINSIC_ROUND:
7066 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7067 case TargetOpcode::G_INTRINSIC_TRUNC:
7068 case TargetOpcode::G_BITREVERSE:
7069 case TargetOpcode::G_BSWAP:
7070 case TargetOpcode::G_FCANONICALIZE:
7071 case TargetOpcode::G_SEXT_INREG:
7072 case TargetOpcode::G_ABS:
7073 case TargetOpcode::G_CTLZ:
7074 case TargetOpcode::G_CTPOP:
7082 case TargetOpcode::G_SELECT: {
7083 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7085 if (!CondTy.isScalar() ||
7091 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7093 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7098 if (CondTy.isVector())
7108 case TargetOpcode::G_UNMERGE_VALUES:
7110 case TargetOpcode::G_PHI:
7112 case TargetOpcode::G_SHUFFLE_VECTOR:
7114 case TargetOpcode::G_BUILD_VECTOR: {
7116 for (
auto Op :
MI.uses()) {
7124 MIRBuilder.buildDeleteTrailingVectorElements(
7125 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7126 MI.eraseFromParent();
7129 case TargetOpcode::G_SEXT:
7130 case TargetOpcode::G_ZEXT:
7131 case TargetOpcode::G_ANYEXT:
7132 case TargetOpcode::G_TRUNC:
7133 case TargetOpcode::G_FPTRUNC:
7134 case TargetOpcode::G_FPEXT:
7135 case TargetOpcode::G_FPTOSI:
7136 case TargetOpcode::G_FPTOUI:
7137 case TargetOpcode::G_FPTOSI_SAT:
7138 case TargetOpcode::G_FPTOUI_SAT:
7139 case TargetOpcode::G_SITOFP:
7140 case TargetOpcode::G_UITOFP:
7141 case TargetOpcode::G_TRUNC_SSAT_S:
7142 case TargetOpcode::G_TRUNC_SSAT_U:
7143 case TargetOpcode::G_TRUNC_USAT_U: {
7150 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7153 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7161 case TargetOpcode::G_ICMP:
7162 case TargetOpcode::G_FCMP: {
7170 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7175 case TargetOpcode::G_BITCAST: {
7179 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7180 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7196 case TargetOpcode::G_VECREDUCE_FADD:
7197 case TargetOpcode::G_VECREDUCE_FMUL:
7198 case TargetOpcode::G_VECREDUCE_ADD:
7199 case TargetOpcode::G_VECREDUCE_MUL:
7200 case TargetOpcode::G_VECREDUCE_AND:
7201 case TargetOpcode::G_VECREDUCE_OR:
7202 case TargetOpcode::G_VECREDUCE_XOR:
7203 case TargetOpcode::G_VECREDUCE_SMAX:
7204 case TargetOpcode::G_VECREDUCE_SMIN:
7205 case TargetOpcode::G_VECREDUCE_UMAX:
7206 case TargetOpcode::G_VECREDUCE_UMIN: {
7207 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7209 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7210 auto NeutralElement = getNeutralElementForVecReduce(
7216 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7217 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7218 NeutralElement, Idx);
7222 MO.
setReg(NewVec.getReg(0));
7234 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7236 unsigned MaskNumElts = Mask.size();
7237 unsigned SrcNumElts = SrcTy.getNumElements();
7240 if (MaskNumElts == SrcNumElts)
7243 if (MaskNumElts < SrcNumElts) {
7251 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7252 MI.getOperand(1).getReg(),
7253 MI.getOperand(2).getReg(), NewMask);
7254 MI.eraseFromParent();
7259 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7260 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7269 MOps1[0] =
MI.getOperand(1).getReg();
7270 MOps2[0] =
MI.getOperand(2).getReg();
7272 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7273 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7277 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7279 if (Idx >=
static_cast<int>(SrcNumElts))
7280 Idx += PaddedMaskNumElts - SrcNumElts;
7285 if (MaskNumElts != PaddedMaskNumElts) {
7287 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7290 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7292 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7297 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7300 MI.eraseFromParent();
7306 unsigned int TypeIdx,
LLT MoreTy) {
7307 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7309 unsigned NumElts = DstTy.getNumElements();
7312 if (DstTy.isVector() && Src1Ty.isVector() &&
7313 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7321 if (DstTy != Src1Ty || DstTy != Src2Ty)
7329 for (
unsigned I = 0;
I != NumElts; ++
I) {
7331 if (Idx <
static_cast<int>(NumElts))
7334 NewMask[
I] = Idx - NumElts + WidenNumElts;
7338 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7339 MI.getOperand(1).getReg(),
7340 MI.getOperand(2).getReg(), NewMask);
7341 MI.eraseFromParent();
7350 unsigned SrcParts = Src1Regs.
size();
7351 unsigned DstParts = DstRegs.
size();
7353 unsigned DstIdx = 0;
7355 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7356 DstRegs[DstIdx] = FactorSum;
7361 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7363 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7364 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7366 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7372 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7373 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7374 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7375 unsigned i = RevI - 1;
7377 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7387 if (DstIdx != DstParts - 1) {
7388 MachineInstrBuilder Uaddo =
7389 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7390 FactorSum = Uaddo.
getReg(0);
7391 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7392 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7393 MachineInstrBuilder Uaddo =
7394 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7395 FactorSum = Uaddo.
getReg(0);
7396 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7397 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7401 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7402 for (
unsigned i = 2; i < Factors.
size(); ++i)
7403 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7406 CarrySumPrevDstIdx = CarrySum;
7407 DstRegs[DstIdx] = FactorSum;
7419 LLT DstType = MRI.getType(DstReg);
7421 if (DstType.isVector())
7424 unsigned Opcode =
MI.getOpcode();
7425 unsigned OpO, OpE, OpF;
7427 case TargetOpcode::G_SADDO:
7428 case TargetOpcode::G_SADDE:
7429 case TargetOpcode::G_UADDO:
7430 case TargetOpcode::G_UADDE:
7431 case TargetOpcode::G_ADD:
7432 OpO = TargetOpcode::G_UADDO;
7433 OpE = TargetOpcode::G_UADDE;
7434 OpF = TargetOpcode::G_UADDE;
7435 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7436 OpF = TargetOpcode::G_SADDE;
7438 case TargetOpcode::G_SSUBO:
7439 case TargetOpcode::G_SSUBE:
7440 case TargetOpcode::G_USUBO:
7441 case TargetOpcode::G_USUBE:
7442 case TargetOpcode::G_SUB:
7443 OpO = TargetOpcode::G_USUBO;
7444 OpE = TargetOpcode::G_USUBE;
7445 OpF = TargetOpcode::G_USUBE;
7446 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7447 OpF = TargetOpcode::G_SSUBE;
7454 unsigned NumDefs =
MI.getNumExplicitDefs();
7455 Register Src1 =
MI.getOperand(NumDefs).getReg();
7456 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7459 CarryDst =
MI.getOperand(1).getReg();
7460 if (
MI.getNumOperands() == NumDefs + 3)
7461 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7463 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7464 LLT LeftoverTy, DummyTy;
7466 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7471 int NarrowParts = Src1Regs.
size();
7472 Src1Regs.
append(Src1Left);
7473 Src2Regs.
append(Src2Left);
7476 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7478 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7481 if (i == e - 1 && CarryDst)
7482 CarryOut = CarryDst;
7484 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7487 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7488 {Src1Regs[i], Src2Regs[i]});
7489 }
else if (i == e - 1) {
7490 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7491 {Src1Regs[i], Src2Regs[i], CarryIn});
7493 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7494 {Src1Regs[i], Src2Regs[i], CarryIn});
7500 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7501 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7502 ArrayRef(DstRegs).drop_front(NarrowParts));
7504 MI.eraseFromParent();
7510 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7512 LLT Ty = MRI.getType(DstReg);
7516 unsigned Size = Ty.getSizeInBits();
7518 if (
Size % NarrowSize != 0)
7521 unsigned NumParts =
Size / NarrowSize;
7522 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7523 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7529 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7533 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7534 MI.eraseFromParent();
7544 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7547 LLT SrcTy = MRI.getType(Src);
7559 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7572 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7575 if (SizeOp1 % NarrowSize != 0)
7577 int NumParts = SizeOp1 / NarrowSize;
7580 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7584 uint64_t OpStart =
MI.getOperand(2).getImm();
7585 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7586 for (
int i = 0; i < NumParts; ++i) {
7587 unsigned SrcStart = i * NarrowSize;
7589 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7592 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7600 int64_t ExtractOffset;
7602 if (OpStart < SrcStart) {
7604 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7606 ExtractOffset = OpStart - SrcStart;
7607 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7611 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7613 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7614 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7621 if (MRI.getType(DstReg).isVector())
7622 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7623 else if (DstRegs.
size() > 1)
7624 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7627 MI.eraseFromParent();
7639 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7641 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7644 SrcRegs.
append(LeftoverRegs);
7648 uint64_t OpStart =
MI.getOperand(3).getImm();
7649 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7650 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7651 unsigned DstStart =
I * NarrowSize;
7653 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7661 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7663 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7667 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7675 int64_t ExtractOffset, InsertOffset;
7677 if (OpStart < DstStart) {
7679 ExtractOffset = DstStart - OpStart;
7680 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7682 InsertOffset = OpStart - DstStart;
7684 SegSize = std::min(NarrowSize - InsertOffset, OpSize);
7688 if (ExtractOffset != 0 || SegSize != OpSize) {
7690 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7691 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7694 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7695 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7699 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7703 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7706 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7708 MI.eraseFromParent();
7716 LLT DstTy = MRI.getType(DstReg);
7718 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7724 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7725 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7729 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7730 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7733 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7734 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7735 {Src0Regs[I], Src1Regs[I]});
7739 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7742 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7743 DstLeftoverRegs.
push_back(Inst.getReg(0));
7746 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7747 LeftoverTy, DstLeftoverRegs);
7749 MI.eraseFromParent();
7759 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7761 LLT DstTy = MRI.getType(DstReg);
7766 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7767 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7768 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7770 MI.eraseFromParent();
7780 Register CondReg =
MI.getOperand(1).getReg();
7781 LLT CondTy = MRI.getType(CondReg);
7782 if (CondTy.isVector())
7786 LLT DstTy = MRI.getType(DstReg);
7792 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7793 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7797 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7798 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7801 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7803 CondReg, Src1Regs[
I], Src2Regs[
I]);
7807 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7809 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7813 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7814 LeftoverTy, DstLeftoverRegs);
7816 MI.eraseFromParent();
7826 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7829 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7830 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7833 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7835 auto C_0 =
B.buildConstant(NarrowTy, 0);
7837 UnmergeSrc.getReg(1), C_0);
7838 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7839 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7840 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7841 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7842 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7843 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7845 MI.eraseFromParent();
7858 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7861 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7862 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7865 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7867 auto C_0 =
B.buildConstant(NarrowTy, 0);
7869 UnmergeSrc.getReg(0), C_0);
7870 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7871 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7872 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7873 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7874 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7875 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7877 MI.eraseFromParent();
7890 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7893 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7898 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7902 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7903 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7911 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7912 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7915 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7916 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7918 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7920 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7922 MI.eraseFromParent();
7932 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7935 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7936 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7938 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7939 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7940 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7942 MI.eraseFromParent();
7957 LLT ExpTy = MRI.getType(ExpReg);
7962 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7963 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7964 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7965 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7967 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7969 MI.getOperand(2).setReg(Trunc.getReg(0));
7976 unsigned Opc =
MI.getOpcode();
7979 auto QAction = LI.getAction(Q).Action;
7985 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7988 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7992 case TargetOpcode::G_CTLZ: {
7993 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7994 unsigned Len = SrcTy.getScalarSizeInBits();
7996 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7998 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7999 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
8002 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8003 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
8004 MI.eraseFromParent();
8020 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
8021 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
8024 Op = MIBOp.getReg(0);
8029 MI.eraseFromParent();
8032 case TargetOpcode::G_CTTZ_ZERO_POISON: {
8035 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
8039 case TargetOpcode::G_CTTZ: {
8040 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8042 unsigned Len = SrcTy.getScalarSizeInBits();
8043 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
8046 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
8047 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
8050 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8051 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
8052 MI.eraseFromParent();
8059 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8060 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8062 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8063 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8064 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8065 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8068 MI.eraseFromParent();
8072 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8073 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8077 case TargetOpcode::G_CTPOP: {
8079 LLT Ty = MRI.getType(SrcReg);
8080 unsigned Size = Ty.getScalarSizeInBits();
8092 auto C_1 =
B.buildConstant(Ty, 1);
8093 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8095 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8096 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8097 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8101 auto C_2 =
B.buildConstant(Ty, 2);
8102 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8104 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8105 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8106 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8107 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8114 auto C_4 =
B.buildConstant(Ty, 4);
8115 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8116 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8118 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8119 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8121 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8124 if (
Size == 16 && !Ty.isVector()) {
8126 auto C_8 =
B.buildConstant(Ty, 8);
8127 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8128 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8129 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8130 MI.eraseFromParent();
8139 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8141 auto IsMulSupported = [
this](
const LLT Ty) {
8142 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8145 if (IsMulSupported(Ty)) {
8146 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8147 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8149 auto ResTmp = B8Count;
8150 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8151 auto ShiftC =
B.buildConstant(Ty, Shift);
8152 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8153 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8155 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8157 MI.eraseFromParent();
8160 case TargetOpcode::G_CTLS: {
8161 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8165 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8166 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8168 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8174 MI.eraseFromParent();
8195 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8196 LLT Ty = MRI.getType(Dst);
8197 LLT ShTy = MRI.getType(Z);
8204 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8205 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8210 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8211 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8215 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8228 MI.eraseFromParent();
8234 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8235 LLT Ty = MRI.getType(Dst);
8236 LLT ShTy = MRI.getType(Z);
8239 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8249 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8250 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8251 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8252 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8253 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8257 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8260 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8263 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8265 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8266 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8267 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8270 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8272 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8274 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8277 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8278 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8283 MI.eraseFromParent();
8294 LLT Ty = MRI.getType(Dst);
8295 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8297 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8298 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8301 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8302 return lowerFunnelShiftAsShifts(
MI);
8306 if (Result == UnableToLegalize)
8307 return lowerFunnelShiftAsShifts(
MI);
8312 auto [Dst, Src] =
MI.getFirst2Regs();
8313 LLT DstTy = MRI.getType(Dst);
8314 LLT SrcTy = MRI.getType(Src);
8318 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8326 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8330 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8334 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8339 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8340 {UnmergeSrc.getReg(0)});
8341 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8342 {UnmergeSrc.getReg(1)});
8345 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8347 MI.eraseFromParent();
8364 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8368 LLT DstTy = MRI.getType(DstReg);
8369 LLT SrcTy = MRI.getType(SrcReg);
8377 SrcTy.getElementCount().divideCoefficientBy(2));
8390 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8402 MI.eraseFromParent();
8411 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8412 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8413 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8414 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8415 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8416 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8417 MI.eraseFromParent();
8422 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8424 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8425 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8430 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8431 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8433 return lowerRotateWithReverseRotate(
MI);
8436 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8437 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8438 bool IsFShLegal =
false;
8439 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8440 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8444 MI.eraseFromParent();
8449 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8452 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8457 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8458 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8459 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8465 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8466 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8468 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8474 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8475 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8477 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8479 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8484 MI.eraseFromParent();
8492 auto [Dst, Src] =
MI.getFirst2Regs();
8497 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8510 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8512 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8517 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8519 MI.eraseFromParent();
8527 auto [Dst, Src] =
MI.getFirst2Regs();
8531 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8542 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8543 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8545 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8552 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8553 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8554 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8556 MI.eraseFromParent();
8567 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8568 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8574 MI.eraseFromParent();
8579 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8585 MI.eraseFromParent();
8589 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8609 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8619 MI.eraseFromParent();
8623 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8629 if (DstTy.getScalarSizeInBits() == 32) {
8636 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8637 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8639 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8646 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8647 MI.eraseFromParent();
8655 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8659 if (SrcTy !=
S64 && SrcTy !=
S32)
8661 if (DstTy !=
S32 && DstTy !=
S64)
8688 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8690 MI.eraseFromParent();
8695 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8700 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8707 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8709 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8710 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8712 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8713 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8715 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8717 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8718 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8719 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8722 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8723 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8724 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8726 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask,
K);
8729 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8734 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8735 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8741 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8743 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8744 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8746 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8751 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8752 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8754 MI.eraseFromParent();
8760 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8762 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8763 unsigned SatWidth = DstTy.getScalarSizeInBits();
8767 APInt MinInt, MaxInt;
8790 if (AreExactFloatBounds) {
8792 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8795 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8797 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8806 MI.eraseFromParent();
8811 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8816 MI.eraseFromParent();
8823 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8831 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8841 MI.eraseFromParent();
8847 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8851 MI.eraseFromParent();
8858 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8859 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8860 "Only G_FPEXT and G_FPTRUNC are expected");
8862 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8867 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8869 StoreOpc = TargetOpcode::G_STORE;
8870 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8873 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8874 LoadOpc = TargetOpcode::G_LOAD;
8883 StackTy, StackTyAlign);
8884 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8887 StackTy, StackTyAlign);
8888 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8890 MI.eraseFromParent();
8898 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8899 assert(SrcTy.getScalarType().isBFloat16() &&
8900 "expected a bf16 source for bf16 fpext lowering");
8911 if (DstTy.getScalarType().isFloat32())
8916 MI.eraseFromParent();
8921 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8922 if (SrcTy.getScalarType().isBFloat16() &&
8923 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8935 auto [Dst, Src] =
MI.getFirst2Regs();
8939 if (MRI.getType(Src).isVector())
8943 unsigned Flags =
MI.getFlags();
8946 MI.eraseFromParent();
8950 const unsigned ExpMask = 0x7ff;
8951 const unsigned ExpBiasf64 = 1023;
8952 const unsigned ExpBiasf16 = 15;
8954 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8964 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8971 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8973 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8975 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8979 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8981 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8983 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8984 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8992 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8993 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
9004 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9015 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9031 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9041 MI.eraseFromParent();
9048 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9056 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9082 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9084 MI.eraseFromParent();
9093 LLT OperandTy = MRI.getType(
Op);
9103 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9105 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9106 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9107 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9108 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9109 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9117 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9120 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9122 AbsWide, AbsNarrowAsWide);
9126 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9127 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9129 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9130 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9136 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9142 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9143 MI.eraseFromParent();
9149 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9150 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9153 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9156 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9163 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9164 LLT Ty = MRI.getType(Dst);
9166 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9167 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9168 MI.eraseFromParent();
9173 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9174 LLT Ty = MRI.getType(Src);
9175 auto Flags =
MI.getFlags();
9183 FracToUse = FracPart.getReg(0);
9185 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9189 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9191 FracToUse =
Select.getReg(0);
9194 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9197 MI.eraseFromParent();
9203 case TargetOpcode::G_SMIN:
9205 case TargetOpcode::G_SMAX:
9207 case TargetOpcode::G_UMIN:
9209 case TargetOpcode::G_UMAX:
9217 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9222 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9223 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9225 MI.eraseFromParent();
9234 LLT DstTy = MRI.getType(Dst);
9235 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9245 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9246 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9248 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9251 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9252 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9253 if (TLI.preferSelectsOverBooleanArithmetic(
9256 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9257 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9259 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9260 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9266 unsigned BoolExtOp =
9268 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9269 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9273 MI.eraseFromParent();
9279 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9280 const int Src0Size = Src0Ty.getScalarSizeInBits();
9281 const int Src1Size = Src1Ty.getScalarSizeInBits();
9291 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9292 Src0Ty.getScalarType().isInteger()))
9293 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9295 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9296 Src1Ty.getScalarType().isInteger()))
9297 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9302 auto NotSignBitMask =
MIRBuilder.buildConstant(
9306 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9308 if (Src0Ty == Src1Ty) {
9309 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9310 }
else if (Src0Size > Src1Size) {
9311 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9312 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9313 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9314 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9316 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9317 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9318 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9319 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9325 unsigned Flags =
MI.getFlags();
9330 if (DstTy == DstIntTy)
9331 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9337 MI.eraseFromParent();
9348 switch (
MI.getOpcode()) {
9349 case TargetOpcode::G_FMINNUM:
9350 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9352 case TargetOpcode::G_FMINIMUMNUM:
9353 NewOp = TargetOpcode::G_FMINNUM;
9355 case TargetOpcode::G_FMAXNUM:
9356 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9358 case TargetOpcode::G_FMAXIMUMNUM:
9359 NewOp = TargetOpcode::G_FMAXNUM;
9365 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9366 LLT Ty = MRI.getType(Dst);
9375 if (!VT->isKnownNeverSNaN(Src0))
9376 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9378 if (!VT->isKnownNeverSNaN(Src1))
9379 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9384 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9385 MI.eraseFromParent();
9391 unsigned Opc =
MI.getOpcode();
9392 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9393 LLT Ty = MRI.getType(Dst);
9396 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9398 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9399 unsigned OpcNonIeee =
9400 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9401 bool MinMaxMustRespectOrderedZero =
false;
9405 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9407 MinMaxMustRespectOrderedZero =
true;
9408 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9413 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9418 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9421 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9425 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9427 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9437 const unsigned Flags =
MI.getFlags();
9443 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9445 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9447 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9449 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9451 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9456 MI.eraseFromParent();
9463 LLT Ty = MRI.getType(DstReg);
9464 unsigned Flags =
MI.getFlags();
9469 MI.eraseFromParent();
9475 auto [DstReg,
X] =
MI.getFirst2Regs();
9476 const unsigned Flags =
MI.getFlags();
9477 const LLT Ty = MRI.getType(DstReg);
9489 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9491 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9496 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9497 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9498 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9499 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9501 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9503 MI.eraseFromParent();
9508 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9509 unsigned Flags =
MI.getFlags();
9510 LLT Ty = MRI.getType(DstReg);
9517 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9518 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9521 SrcReg, Zero, Flags);
9523 SrcReg, Trunc, Flags);
9527 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9528 MI.eraseFromParent();
9534 const unsigned NumOps =
MI.getNumOperands();
9535 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9536 unsigned PartSize = Src0Ty.getSizeInBits();
9541 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9542 const unsigned Offset = (
I - 1) * PartSize;
9545 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9548 MRI.createGenericVirtualRegister(WideTy);
9551 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9552 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9553 ResultReg = NextResult;
9556 if (DstTy.isPointer()) {
9557 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9558 DstTy.getAddressSpace())) {
9564 }
else if (WideTy != DstTy) {
9568 MI.eraseFromParent();
9574 const unsigned NumDst =
MI.getNumOperands() - 1;
9575 Register SrcReg =
MI.getOperand(NumDst).getReg();
9576 Register Dst0Reg =
MI.getOperand(0).getReg();
9577 LLT DstTy = MRI.getType(Dst0Reg);
9586 LLT IntTy = MRI.getType(SrcReg);
9591 unsigned Offset = DstSize;
9592 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9594 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9598 MI.eraseFromParent();
9617 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9618 InsertVal =
MI.getOperand(2).getReg();
9620 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9622 LLT VecTy = MRI.getType(SrcVec);
9632 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9633 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9635 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9638 MI.eraseFromParent();
9643 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9654 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9661 int64_t
Offset = IdxVal * EltBytes;
9672 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9675 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9677 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9680 MI.eraseFromParent();
9686 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9687 MI.getFirst3RegLLTs();
9697 for (
int Idx : Mask) {
9699 if (!
Undef.isValid())
9705 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9707 int NumElts = Src0Ty.getNumElements();
9708 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9709 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9710 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9712 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9714 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9719 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9720 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9721 MI.eraseFromParent();
9727 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9728 MI.getFirst4RegLLTs();
9730 if (VecTy.isScalableVector())
9746 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9751 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9754 std::optional<APInt> PassthruSplatVal =
9757 if (PassthruSplatVal.has_value()) {
9759 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9760 }
else if (HasPassthru) {
9761 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9762 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9768 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9772 unsigned NumElmts = VecTy.getNumElements();
9773 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9775 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9778 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9781 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9786 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9788 if (HasPassthru &&
I == NumElmts - 1) {
9791 auto AllLanesSelected =
MIRBuilder.buildICmp(
9793 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9794 {OutPos, EndOfVector});
9798 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9800 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9805 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9807 MI.eraseFromParent();
9824 if (Alignment >
Align(1)) {
9825 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9836 const auto &MF = *
MI.getMF();
9842 Register AllocSize =
MI.getOperand(1).getReg();
9845 LLT PtrTy = MRI.getType(Dst);
9846 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9853 MI.eraseFromParent();
9859 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9864 MI.eraseFromParent();
9870 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9875 MI.eraseFromParent();
9881 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9882 unsigned Offset =
MI.getOperand(2).getImm();
9885 if (SrcTy.isVector()) {
9886 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9887 unsigned DstSize = DstTy.getSizeInBits();
9889 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9890 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9892 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9896 for (
unsigned Idx =
Offset / SrcEltSize;
9897 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9898 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9900 if (SubVectorElts.
size() == 1)
9901 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9903 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9905 MI.eraseFromParent();
9911 if ((SrcTy.isPointer() &&
9912 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9913 (DstTy.isPointer() &&
9914 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9915 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9919 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9920 (SrcTy.isScalar() || SrcTy.isPointer() ||
9921 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9922 LLT SrcIntTy = SrcTy;
9923 if (!SrcTy.isScalar()) {
9925 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9929 if (DstTy.isPointer())
9931 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9937 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9941 if (DstTy.isPointer())
9944 MI.eraseFromParent();
9952 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9953 uint64_t
Offset =
MI.getOperand(3).getImm();
9955 LLT DstTy = MRI.getType(Src);
9956 LLT InsertTy = MRI.getType(InsertSrc);
9959 bool IsNonIntegralInsert =
9969 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9970 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9977 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9979 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9983 for (; Idx <
Offset / EltSize; ++Idx) {
9984 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9989 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9990 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9992 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9996 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
9998 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
10005 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10008 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
10009 MI.eraseFromParent();
10018 if (IsNonIntegralDst || IsNonIntegralInsert) {
10019 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10023 LLT IntDstTy = DstTy;
10027 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
10032 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
10038 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10044 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10045 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10046 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10049 MI.eraseFromParent();
10055 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10056 MI.getFirst4RegLLTs();
10057 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10060 LLT BoolTy = Dst1Ty;
10062 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10071 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10077 auto ResultLowerThanLHS =
10081 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10085 auto LHSLessThanRHS =
10087 auto ResultNegative =
10089 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10093 MI.eraseFromParent();
10099 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10100 const LLT Ty = MRI.getType(Res);
10103 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10104 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10105 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10109 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10110 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10113 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10116 MI.eraseFromParent();
10121 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10122 const LLT Ty = MRI.getType(Res);
10125 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10126 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10127 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10131 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10132 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10134 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10137 MI.eraseFromParent();
10143 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10144 LLT Ty = MRI.getType(Res);
10148 switch (
MI.getOpcode()) {
10151 case TargetOpcode::G_UADDSAT:
10154 BaseOp = TargetOpcode::G_ADD;
10156 case TargetOpcode::G_SADDSAT:
10159 BaseOp = TargetOpcode::G_ADD;
10161 case TargetOpcode::G_USUBSAT:
10164 BaseOp = TargetOpcode::G_SUB;
10166 case TargetOpcode::G_SSUBSAT:
10169 BaseOp = TargetOpcode::G_SUB;
10184 uint64_t NumBits = Ty.getScalarSizeInBits();
10191 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10195 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10203 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10208 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10209 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10212 MI.eraseFromParent();
10218 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10219 LLT Ty = MRI.getType(Res);
10223 unsigned OverflowOp;
10224 switch (
MI.getOpcode()) {
10227 case TargetOpcode::G_UADDSAT:
10230 OverflowOp = TargetOpcode::G_UADDO;
10232 case TargetOpcode::G_SADDSAT:
10235 OverflowOp = TargetOpcode::G_SADDO;
10237 case TargetOpcode::G_USUBSAT:
10240 OverflowOp = TargetOpcode::G_USUBO;
10242 case TargetOpcode::G_SSUBSAT:
10245 OverflowOp = TargetOpcode::G_SSUBO;
10250 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10251 Register Tmp = OverflowRes.getReg(0);
10252 Register Ov = OverflowRes.getReg(1);
10261 uint64_t NumBits = Ty.getScalarSizeInBits();
10262 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10263 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10266 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10274 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10276 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10278 MI.eraseFromParent();
10284 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10285 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10286 "Expected shlsat opcode!");
10287 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10288 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10289 LLT Ty = MRI.getType(Res);
10293 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10294 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10303 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10308 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10310 MI.eraseFromParent();
10316 unsigned Opc =
MI.getOpcode();
10317 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10318 unsigned DstSize = DstTy.getScalarSizeInBits();
10319 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10321 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10324 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10327 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10328 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10331 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10332 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10335 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10337 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10343 MI.eraseFromParent();
10348 auto [Dst, Src] =
MI.getFirst2Regs();
10349 const LLT Ty = MRI.getType(Src);
10350 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10351 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10354 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10355 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10356 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10357 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10360 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10363 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10364 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10366 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10367 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10368 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10370 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10371 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10372 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10374 Res.getInstr()->getOperand(0).setReg(Dst);
10376 MI.eraseFromParent();
10383 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10386 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10387 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10388 return B.buildOr(Dst,
LHS,
RHS);
10393 auto [Dst, Src] =
MI.getFirst2Regs();
10394 const LLT SrcTy = MRI.getType(Src);
10395 unsigned Size = SrcTy.getScalarSizeInBits();
10396 unsigned VSize = SrcTy.getSizeInBits();
10399 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10400 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10401 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10402 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10407 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10408 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10409 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10413 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10436 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10440 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10443 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10447 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10451 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10456 MI.eraseFromParent();
10464 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10465 int NameOpIdx = IsRead ? 1 : 0;
10466 int ValRegIndex = IsRead ? 0 : 1;
10468 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10469 const LLT Ty = MRI.getType(ValReg);
10471 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10478 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10479 Fn,
MI.getDebugLoc()));
10483 MI.eraseFromParent();
10492 MI.eraseFromParent();
10498 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10499 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10500 Register Result =
MI.getOperand(0).getReg();
10501 LLT OrigTy = MRI.getType(Result);
10505 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10506 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10508 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10510 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10511 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10514 MI.eraseFromParent();
10520 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10525 MI.eraseFromParent();
10530 MI.eraseFromParent();
10537 unsigned BitSize = SrcTy.getScalarSizeInBits();
10541 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10548 APInt ExpMask = Inf;
10550 APInt QNaNBitMask =
10554 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10555 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10556 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10557 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10558 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10560 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10564 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10566 LLT DstTyCopy = DstTy;
10568 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10596 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10599 Mask &= ~PartialCheck;
10608 else if (PartialCheck ==
fcZero)
10620 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10621 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10622 auto SubnormalRes =
10624 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10626 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10627 appendToRes(SubnormalRes);
10634 else if (PartialCheck ==
fcInf)
10639 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10646 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10647 if (PartialCheck ==
fcNan) {
10651 }
else if (PartialCheck ==
fcQNan) {
10661 Abs, InfWithQnanBitC);
10662 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10669 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10671 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10672 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10675 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10677 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10680 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10681 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10683 appendToRes(NormalRes);
10687 MI.eraseFromParent();
10693 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10694 MI.getFirst4RegLLTs();
10703 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10704 Op1Ty = MRI.getType(Op1Reg);
10705 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10706 Op2Ty = MRI.getType(Op2Reg);
10710 if (MaskTy.isScalar()) {
10718 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10721 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10723 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10725 if (DstTy.isVector()) {
10727 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10728 MaskReg = ShufSplat.getReg(0);
10732 }
else if (!DstTy.isVector()) {
10737 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10741 if (!Op1Ty.getScalarType().isAnyScalar() &&
10742 !Op1Ty.getScalarType().isInteger())
10743 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10745 if (!Op2Ty.getScalarType().isAnyScalar() &&
10746 !Op2Ty.getScalarType().isInteger()) {
10748 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10749 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10752 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10753 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10754 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10759 if (DstTy == Op1TyInt)
10762 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10766 MI.eraseFromParent();
10772 unsigned Opcode =
MI.getOpcode();
10775 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10776 : TargetOpcode::G_UDIV,
10777 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10779 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10780 : TargetOpcode::G_UREM,
10781 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10782 MI.eraseFromParent();
10792 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10796 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10799 MI.eraseFromParent();
10809 Register SrcReg =
MI.getOperand(1).getReg();
10810 LLT Ty = MRI.getType(SrcReg);
10811 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10814 MI.eraseFromParent();
10820 Register SrcReg =
MI.getOperand(1).getReg();
10821 Register DestReg =
MI.getOperand(0).getReg();
10823 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10824 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10827 MI.eraseFromParent();
10833 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10834 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10835 "Expected G_ABDS or G_ABDU instruction");
10837 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10838 LLT Ty = MRI.getType(LHS);
10848 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10850 MI.eraseFromParent();
10856 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10857 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10858 "Expected G_ABDS or G_ABDU instruction");
10860 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10861 LLT Ty = MRI.getType(LHS);
10866 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10867 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10868 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10870 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10871 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10873 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10875 MI.eraseFromParent();
10880 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10885 if (!(SrcTy.getScalarType().isAnyScalar() ||
10886 SrcTy.getScalarType().isInteger())) {
10888 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10889 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10892 if (MRI.getType(DstReg) != TyInt) {
10896 .buildAnd(TyInt, CastedSrc,
10899 DstTy.getScalarSizeInBits())))
10911 MI.eraseFromParent();
10917 Register SrcReg =
MI.getOperand(1).getReg();
10918 LLT SrcTy = MRI.getType(SrcReg);
10919 LLT DstTy = MRI.getType(SrcReg);
10922 if (SrcTy.isScalar()) {
10927 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10938 Register ListPtr =
MI.getOperand(1).getReg();
10939 LLT PtrTy = MRI.getType(ListPtr);
10946 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10948 const Align A(
MI.getOperand(2).getImm());
10950 if (
A > TLI.getMinStackArgumentAlignment()) {
10952 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10953 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10954 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10955 VAList = AndDst.getReg(0);
10962 LLT LLTTy = MRI.getType(Dst);
10965 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10966 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10971 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10973 Align EltAlignment =
DL.getABITypeAlign(Ty);
10976 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10978 MI.eraseFromParent();
10983 unsigned OpCode =
MI.getOpcode();
10984 assert((OpCode == TargetOpcode::G_SMULFIX ||
10985 OpCode == TargetOpcode::G_UMULFIX ||
10986 OpCode == TargetOpcode::G_SMULFIXSAT ||
10987 OpCode == TargetOpcode::G_UMULFIXSAT) &&
10988 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
10989 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10990 LLT Ty = MRI.getType(Dst);
10991 unsigned Scale =
MI.getOperand(3).getImm();
10993 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
10994 OpCode == TargetOpcode::G_UMULFIXSAT);
10995 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
10996 OpCode == TargetOpcode::G_SMULFIXSAT);
10998 if (!Saturating && Scale == 0) {
11000 MI.eraseFromParent();
11006 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
11029 MI.eraseFromParent();
11036 unsigned NumBits = Ty.getScalarSizeInBits();
11038 if (!Ty.isVector() && ValVRegAndVal) {
11039 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
11047 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11070 auto &MF = *
MI.getParent()->getParent();
11075 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11076 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11079 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11080 const auto &DstMMO = **
MI.memoperands_begin();
11082 if (DstAlignCanChange) {
11085 Align NewAlign =
DL.getABITypeAlign(IRTy);
11086 if (NewAlign > Alignment) {
11095 MachineIRBuilder MIB(
MI);
11097 LLT LargestTy = MemOps[0];
11098 for (
unsigned i = 1; i < MemOps.
size(); i++)
11100 LargestTy = MemOps[i];
11112 LLT PtrTy = MRI.getType(Dst);
11113 unsigned DstOff = 0;
11114 unsigned Size = KnownLen;
11115 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11116 LLT Ty = MemOps[
I];
11119 if (TySize >
Size) {
11123 DstOff -= TySize -
Size;
11133 TLI.isTruncateFree(LargestVT, VT))
11134 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11147 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11150 MIB.buildStore(
Value, Ptr, *StoreMMO);
11155 MI.eraseFromParent();
11163 auto &MF = *
MI.getParent()->getParent();
11167 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11168 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11171 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11177 const auto &DstMMO = **
MI.memoperands_begin();
11178 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11180 if (DstAlignCanChange) {
11183 Align NewAlign =
DL.getABITypeAlign(IRTy);
11188 if (!
TRI->hasStackRealignment(MF))
11189 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11190 NewAlign = std::min(NewAlign, *StackAlign);
11192 if (NewAlign > Alignment) {
11201 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11203 MachineIRBuilder MIB(
MI);
11209 unsigned CurrOffset = 0;
11210 unsigned Size = KnownLen;
11211 for (
auto CopyTy : MemOps) {
11212 TypeSize TySize = CopyTy.getSizeInBytes();
11216 if (TySize >
Size) {
11217 unsigned Overlap = TySize -
Size;
11218 assert(Overlap < CurrOffset &&
11219 "overlapping memcpy load/store spans the whole region or more");
11220 CurrOffset -= Overlap;
11230 if (CurrOffset != 0) {
11231 LLT SrcTy = MRI.getType(Src);
11235 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11237 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11241 if (CurrOffset != 0) {
11242 LLT DstTy = MRI.getType(Dst);
11243 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11245 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11246 CurrOffset += TySize;
11250 MI.eraseFromParent();
11258 auto &MF = *
MI.getParent()->getParent();
11262 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11263 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11266 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11267 const auto &DstMMO = **
MI.memoperands_begin();
11268 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11270 if (DstAlignCanChange) {
11273 Align NewAlign =
DL.getABITypeAlign(IRTy);
11278 if (!
TRI->hasStackRealignment(MF))
11279 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11280 NewAlign = std::min(NewAlign, *StackAlign);
11282 if (NewAlign > Alignment) {
11291 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11293 MachineIRBuilder MIB(
MI);
11297 unsigned CurrOffset = 0;
11298 unsigned Size = KnownLen;
11299 SmallVector<Register, 16> LoadVals;
11300 for (
auto CopyTy : MemOps) {
11301 TypeSize TySize = CopyTy.getSizeInBytes();
11305 if (TySize >
Size) {
11306 unsigned Overlap = TySize -
Size;
11307 assert(Overlap < CurrOffset &&
11308 "overlapping memmove load spans the whole region or more");
11309 CurrOffset -= Overlap;
11317 if (CurrOffset != 0) {
11318 LLT SrcTy = MRI.getType(Src);
11321 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11323 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11324 CurrOffset += TySize;
11330 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11331 LLT CopyTy = MemOps[
I];
11336 if (TySize >
Size) {
11337 unsigned Overlap = TySize -
Size;
11338 assert(Overlap < CurrOffset &&
11339 "overlapping memmove store spans the whole region or more");
11340 CurrOffset -= Overlap;
11347 if (CurrOffset != 0) {
11348 LLT DstTy = MRI.getType(Dst);
11351 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11353 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11354 CurrOffset += TySize;
11357 MI.eraseFromParent();
11364 const unsigned Opc =
MI.getOpcode();
11365 assert((
Opc == TargetOpcode::G_MEMCPY ||
11366 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11367 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11368 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11369 "Expected memcpy like instruction");
11371 if (KnownLen == 0) {
11372 MI.eraseFromParent();
11376 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11377 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11380 if (
Opc == TargetOpcode::G_MEMMOVE)
11381 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11383 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11384 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11394 bool DstAlignCanChange;
11395 std::vector<LLT> MemOps;
11397 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
LLT changeToInteger() 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 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 lowerTruncSat(MachineInstr &MI)
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 or function.
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.
LLVM_ABI unsigned getIntegerBitWidth() const
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)
ImplicitDefMatch m_GImplicitDef()
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 bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, llvm::function_ref< 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...
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.)
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.
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.