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 = EVT(TLI.getCmpLibcallReturnType()).getTypeForEVT(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()) {
3761 int NumDstElt = DstTy.getNumElements();
3762 int NumSrcElt = SrcTy.getNumElements();
3765 LLT DstCastTy = DstEltTy;
3766 LLT SrcPartTy = SrcEltTy;
3770 if (NumSrcElt < NumDstElt) {
3781 SrcPartTy = SrcEltTy;
3782 }
else if (NumSrcElt > NumDstElt) {
3794 DstCastTy = DstEltTy;
3799 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3803 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3804 MI.eraseFromParent();
3808 if (DstTy.isVector()) {
3811 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3812 MI.eraseFromParent();
3828 unsigned NewEltSize,
3829 unsigned OldEltSize) {
3830 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3831 LLT IdxTy =
B.getMRI()->getType(Idx);
3834 auto OffsetMask =
B.buildConstant(
3836 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3837 return B.buildShl(IdxTy, OffsetIdx,
3838 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3853 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3857 unsigned OldNumElts = SrcVecTy.getNumElements();
3864 if (NewNumElts > OldNumElts) {
3875 if (NewNumElts % OldNumElts != 0)
3879 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3883 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3886 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3888 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3889 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3890 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3891 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3892 NewOps[
I] = Elt.getReg(0);
3895 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3897 MI.eraseFromParent();
3901 if (NewNumElts < OldNumElts) {
3902 if (NewEltSize % OldEltSize != 0)
3924 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3925 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3928 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3932 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3933 ScaledIdx).getReg(0);
3941 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3943 MI.eraseFromParent();
3957 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3958 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3959 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3960 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3963 auto EltMask =
B.buildConstant(
3967 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3968 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3971 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3975 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3989 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3990 MI.getFirst4RegLLTs();
4002 if (NewNumElts < OldNumElts) {
4003 if (NewEltSize % OldEltSize != 0)
4012 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4013 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4016 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4020 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4021 ScaledIdx).getReg(0);
4031 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4032 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4036 MI.eraseFromParent();
4066 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4070 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4071 return UnableToLegalize;
4076 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4078 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4087 MI.eraseFromParent();
4105 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4106 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4116 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4117 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4119 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4120 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4122 MI.eraseFromParent();
4148 uint64_t Idx = ES->getIndexImm();
4152 LLT DstTy = MRI.getType(Dst);
4153 LLT SrcTy = MRI.getType(Src);
4159 if (DstTy == CastTy)
4167 if (CastEltSize < DstEltSize)
4170 auto AdjustAmt = CastEltSize / DstEltSize;
4171 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4172 SrcTyMinElts % AdjustAmt != 0)
4177 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4178 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4181 ES->eraseFromParent();
4212 uint64_t Idx = ES->getIndexImm();
4216 LLT DstTy = MRI.getType(Dst);
4217 LLT BigVecTy = MRI.getType(BigVec);
4218 LLT SubVecTy = MRI.getType(SubVec);
4220 if (DstTy == CastTy)
4235 if (CastEltSize < DstEltSize)
4238 auto AdjustAmt = CastEltSize / DstEltSize;
4239 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4240 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4246 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4247 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4249 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4252 ES->eraseFromParent();
4260 LLT DstTy = MRI.getType(DstReg);
4270 if (MemSizeInBits != MemStoreSizeInBits) {
4287 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4291 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4292 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4294 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4297 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4299 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4302 if (DstTy != LoadTy)
4310 if (
MIRBuilder.getDataLayout().isBigEndian())
4328 uint64_t LargeSplitSize, SmallSplitSize;
4333 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4340 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4343 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4354 if (Alignment.value() * 8 > MemSizeInBits &&
4359 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4376 LLT PtrTy = MRI.getType(PtrReg);
4389 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4392 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4393 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4394 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4396 SmallPtr, *SmallMMO);
4398 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4399 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4401 if (AnyExtTy == DstTy)
4402 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4404 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4408 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4428 LLT SrcTy = MRI.getType(SrcReg);
4436 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4442 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4444 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4448 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4452 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4467 uint64_t LargeSplitSize, SmallSplitSize;
4474 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4477 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4486 if (SrcTy.isPointer()) {
4491 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4494 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4495 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4498 LLT PtrTy = MRI.getType(PtrReg);
4500 LargeSplitSize / 8);
4501 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4507 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4508 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4517 LLT SrcTy = MRI.getType(SrcReg);
4523 assert(SrcTy.isVector() &&
"Expect a vector store type");
4530 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4534 auto Elt =
MIRBuilder.buildExtractVectorElement(
4535 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4536 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4537 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4543 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4544 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4548 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4559 switch (
MI.getOpcode()) {
4560 case TargetOpcode::G_LOAD: {
4578 case TargetOpcode::G_STORE: {
4594 case TargetOpcode::G_SELECT: {
4598 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4600 dbgs() <<
"bitcast action not implemented for vector select\n");
4611 case TargetOpcode::G_AND:
4612 case TargetOpcode::G_OR:
4613 case TargetOpcode::G_XOR: {
4621 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4623 case TargetOpcode::G_INSERT_VECTOR_ELT:
4625 case TargetOpcode::G_CONCAT_VECTORS:
4627 case TargetOpcode::G_SHUFFLE_VECTOR:
4629 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4631 case TargetOpcode::G_INSERT_SUBVECTOR:
4639void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4648 switch(
MI.getOpcode()) {
4651 case TargetOpcode::G_FCONSTANT:
4653 case TargetOpcode::G_BITCAST:
4655 case TargetOpcode::G_SREM:
4656 case TargetOpcode::G_UREM: {
4657 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4659 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4660 {MI.getOperand(1), MI.getOperand(2)});
4662 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4664 MI.eraseFromParent();
4667 case TargetOpcode::G_SADDO:
4668 case TargetOpcode::G_SSUBO:
4670 case TargetOpcode::G_SADDE:
4672 case TargetOpcode::G_SSUBE:
4674 case TargetOpcode::G_UMULH:
4675 case TargetOpcode::G_SMULH:
4677 case TargetOpcode::G_SMULO:
4678 case TargetOpcode::G_UMULO: {
4681 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4682 LLT Ty = MRI.getType(Res);
4684 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4685 ? TargetOpcode::G_SMULH
4686 : TargetOpcode::G_UMULH;
4690 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4691 MI.removeOperand(1);
4694 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4702 if (Opcode == TargetOpcode::G_SMULH) {
4703 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4704 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4711 case TargetOpcode::G_FNEG: {
4712 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4715 Register CastedSubByReg = SubByReg;
4717 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4718 !SubByRegTy.getScalarType().isInteger()) {
4719 auto BitcastDst = SubByRegTy.changeElementType(
4721 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4727 if (ResTy != TyInt) {
4729 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4732 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4734 MI.eraseFromParent();
4737 case TargetOpcode::G_FSUB:
4738 case TargetOpcode::G_STRICT_FSUB: {
4739 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4740 LLT Ty = MRI.getType(Res);
4745 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4746 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4750 MI.eraseFromParent();
4753 case TargetOpcode::G_FMAD:
4755 case TargetOpcode::G_FFLOOR:
4757 case TargetOpcode::G_LROUND:
4758 case TargetOpcode::G_LLROUND: {
4761 LLT SrcTy = MRI.getType(SrcReg);
4762 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4765 MI.eraseFromParent();
4768 case TargetOpcode::G_INTRINSIC_ROUND:
4770 case TargetOpcode::G_FRINT: {
4773 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4776 case TargetOpcode::G_INTRINSIC_LRINT:
4777 case TargetOpcode::G_INTRINSIC_LLRINT: {
4780 LLT SrcTy = MRI.getType(SrcReg);
4782 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4784 MI.eraseFromParent();
4787 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4788 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4789 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4790 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4791 **
MI.memoperands_begin());
4793 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4794 MI.eraseFromParent();
4797 case TargetOpcode::G_LOAD:
4798 case TargetOpcode::G_SEXTLOAD:
4799 case TargetOpcode::G_ZEXTLOAD:
4801 case TargetOpcode::G_STORE:
4803 case TargetOpcode::G_CTLZ_ZERO_POISON:
4804 case TargetOpcode::G_CTTZ_ZERO_POISON:
4805 case TargetOpcode::G_CTLZ:
4806 case TargetOpcode::G_CTTZ:
4807 case TargetOpcode::G_CTPOP:
4808 case TargetOpcode::G_CTLS:
4811 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4813 Register NewRes = MRI.cloneVirtualRegister(Res);
4820 MI.eraseFromParent();
4824 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4825 const LLT CondTy = MRI.getType(CarryOut);
4826 const LLT Ty = MRI.getType(Res);
4828 Register NewRes = MRI.cloneVirtualRegister(Res);
4831 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4837 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4838 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4845 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4850 MI.eraseFromParent();
4854 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4859 MI.eraseFromParent();
4863 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4864 const LLT CondTy = MRI.getType(BorrowOut);
4865 const LLT Ty = MRI.getType(Res);
4868 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4874 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4875 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4882 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4883 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4885 MI.eraseFromParent();
4925 case G_MERGE_VALUES:
4927 case G_UNMERGE_VALUES:
4929 case TargetOpcode::G_SEXT_INREG: {
4930 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4931 int64_t SizeInBits =
MI.getOperand(2).getImm();
4933 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4934 LLT DstTy = MRI.getType(DstReg);
4935 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4938 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4939 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4940 MI.eraseFromParent();
4943 case G_EXTRACT_VECTOR_ELT:
4944 case G_INSERT_VECTOR_ELT:
4946 case G_SHUFFLE_VECTOR:
4948 case G_VECTOR_COMPRESS:
4950 case G_DYN_STACKALLOC:
4952 case G_INSERT_SUBVECTOR: {
4953 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4954 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4959 Register Subvector =
MI.getOperand(2).getReg();
4960 auto InsertionPointImm =
MI.getOperand(3).getImm();
4963 LLT DstTy = MRI.getType(Subvector);
4967 bool InsertInLowHalf = InsertionPointImm == 0;
4968 auto Extract =
MIRBuilder.buildExtractSubvector(
4970 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
4972 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4973 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4975 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4976 {LowHalf, HighHalf});
4977 MI.eraseFromParent();
4983 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4984 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4990 if (i >= InsertionPointImm &&
4992 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
5000 MI.eraseFromParent();
5004 case G_EXTRACT_SUBVECTOR: {
5007 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5009 LLT SrcTy = MRI.getType(SrcReg);
5010 LLT DstTy = MRI.getType(DstReg);
5012 if (SrcTy.isScalable())
5023 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5024 ExtractionPointImm + i)
5028 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5029 MI.eraseFromParent();
5034 case G_STACKRESTORE:
5044 case G_READ_REGISTER:
5045 case G_WRITE_REGISTER:
5052 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5053 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5059 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5064 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5071 case G_TRUNC_SSAT_S:
5072 case G_TRUNC_USAT_U:
5073 case G_TRUNC_SSAT_U:
5079 bool IsSigned =
MI.getOpcode() == G_ABDS;
5080 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5081 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5082 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5105 case G_MEMCPY_INLINE:
5106 case G_MEMSET_INLINE:
5118 case G_ATOMICRMW_SUB: {
5119 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5120 const LLT ValTy = MRI.getType(Val);
5124 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5125 MI.eraseFromParent();
5153 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5157 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5163 Align StackTypeAlign =
5170 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5171 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5176 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5188 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5191 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5202 "Converting bits to bytes lost precision");
5208 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5209 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5211 if (IdxTy != MRI.getType(Index))
5212 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5217 LLT PtrTy = MRI.getType(VecPtr);
5218 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5226 std::initializer_list<unsigned> NonVecOpIndices) {
5227 if (
MI.getNumMemOperands() != 0)
5235 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5244 if (!Ty.isVector()) {
5250 if (Ty.getNumElements() != NumElts)
5265 assert(Ty.isVector() &&
"Expected vector type");
5267 int NumParts, NumLeftover;
5268 std::tie(NumParts, NumLeftover) =
5271 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5272 for (
int i = 0; i < NumParts; ++i) {
5277 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5286 for (
unsigned i = 0; i <
N; ++i) {
5288 Ops.push_back(
Op.getReg());
5289 else if (
Op.isImm())
5290 Ops.push_back(
Op.getImm());
5291 else if (
Op.isPredicate())
5313 std::initializer_list<unsigned> NonVecOpIndices) {
5315 "Non-compatible opcode or not specified non-vector operands");
5316 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5318 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5319 unsigned NumDefs =
MI.getNumDefs();
5327 for (
unsigned i = 0; i < NumDefs; ++i) {
5328 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5336 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5337 ++UseIdx, ++UseNo) {
5340 MI.getOperand(UseIdx));
5349 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5353 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5355 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5356 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5359 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5360 Uses.push_back(InputOpsPieces[InputNo][i]);
5363 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5364 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5369 for (
unsigned i = 0; i < NumDefs; ++i)
5370 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5372 for (
unsigned i = 0; i < NumDefs; ++i)
5373 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5376 MI.eraseFromParent();
5383 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5385 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5386 unsigned NumDefs =
MI.getNumDefs();
5390 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5395 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5396 UseIdx += 2, ++UseNo) {
5404 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5406 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5407 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5409 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5412 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5413 Phi.addUse(InputOpsPieces[j][i]);
5414 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5424 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5426 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5429 MI.eraseFromParent();
5437 const int NumDst =
MI.getNumOperands() - 1;
5438 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5439 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5440 LLT SrcTy = MRI.getType(SrcReg);
5442 if (TypeIdx != 1 || NarrowTy == DstTy)
5449 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5452 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5466 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5467 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5468 const int PartsPerUnmerge = NumDst / NumUnmerge;
5470 for (
int I = 0;
I != NumUnmerge; ++
I) {
5471 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5473 for (
int J = 0; J != PartsPerUnmerge; ++J)
5474 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5475 MIB.addUse(Unmerge.getReg(
I));
5478 MI.eraseFromParent();
5485 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5489 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5491 if (NarrowTy == SrcTy)
5499 assert(SrcTy.isVector() &&
"Expected vector types");
5501 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5515 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5516 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5517 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5523 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5524 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5525 ++i,
Offset += NumNarrowTyElts) {
5528 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5531 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5532 MI.eraseFromParent();
5536 assert(TypeIdx == 0 &&
"Bad type index");
5537 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5552 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5553 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5555 for (
unsigned i = 0; i < NumParts; ++i) {
5557 for (
unsigned j = 0; j < NumElts; ++j)
5558 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5560 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5563 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5564 MI.eraseFromParent();
5572 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5574 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5576 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5578 InsertVal =
MI.getOperand(2).getReg();
5580 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5581 LLT VecTy = MRI.getType(SrcVec);
5587 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5591 MI.eraseFromParent();
5600 SplitPieces[IdxVal] = InsertVal;
5601 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5603 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5607 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5610 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5611 TargetOpcode::G_ANYEXT);
5615 LLT IdxTy = MRI.getType(Idx);
5616 int64_t PartIdx = IdxVal / NewNumElts;
5618 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5621 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5624 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5625 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5626 VecParts[PartIdx] = InsertPart.getReg(0);
5630 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5632 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5636 MI.eraseFromParent();
5656 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5668 LLT ValTy = MRI.getType(ValReg);
5677 int NumLeftover = -1;
5683 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5685 NumParts = NarrowRegs.
size();
5686 NumLeftover = NarrowLeftoverRegs.
size();
5693 LLT PtrTy = MRI.getType(AddrReg);
5703 auto MMO = LdStMI.
getMMO();
5705 unsigned NumParts,
unsigned Offset) ->
unsigned {
5708 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5710 unsigned ByteOffset =
Offset / 8;
5713 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5720 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5721 ValRegs.push_back(Dst);
5722 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5724 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5733 unsigned HandledOffset =
5734 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5738 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5741 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5742 LeftoverTy, NarrowLeftoverRegs);
5756 switch (
MI.getOpcode()) {
5757 case G_IMPLICIT_DEF:
5773 case G_FCANONICALIZE:
5790 case G_INTRINSIC_LRINT:
5791 case G_INTRINSIC_LLRINT:
5792 case G_INTRINSIC_ROUND:
5793 case G_INTRINSIC_ROUNDEVEN:
5796 case G_INTRINSIC_TRUNC:
5824 case G_FMINNUM_IEEE:
5825 case G_FMAXNUM_IEEE:
5847 case G_CTLZ_ZERO_POISON:
5849 case G_CTTZ_ZERO_POISON:
5866 case G_ADDRSPACE_CAST:
5879 case G_STRICT_FLDEXP:
5881 case G_TRUNC_SSAT_S:
5882 case G_TRUNC_SSAT_U:
5883 case G_TRUNC_USAT_U:
5891 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5896 case G_UNMERGE_VALUES:
5898 case G_BUILD_VECTOR:
5899 assert(TypeIdx == 0 &&
"not a vector type index");
5901 case G_CONCAT_VECTORS:
5905 case G_EXTRACT_SUBVECTOR: {
5907 LLT DstTy = MRI.getType(DstReg);
5909 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5919 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5920 uint64_t RequiredSubvectorIndex =
5924 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5927 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5930 MI.eraseFromParent();
5933 case G_EXTRACT_VECTOR_ELT:
5934 case G_INSERT_VECTOR_ELT:
5943 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5944 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5946 case G_SHUFFLE_VECTOR:
5952 case G_INTRINSIC_FPTRUNC_ROUND:
5962 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5963 "Not a bitcast operation");
5968 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5970 unsigned NewElemCount =
5973 if (NewElemCount == 1) {
5976 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5983 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5992 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5993 MI.eraseFromParent();
5999 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6003 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6004 MI.getFirst3RegLLTs();
6007 if (DstTy != Src1Ty)
6009 if (DstTy != Src2Ty)
6024 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6040 unsigned InputUsed[2] = {-1U, -1U};
6041 unsigned FirstMaskIdx =
High * NewElts;
6042 bool UseBuildVector =
false;
6043 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6045 int Idx = Mask[FirstMaskIdx + MaskOffset];
6050 if (
Input >= std::size(Inputs)) {
6057 Idx -=
Input * NewElts;
6061 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6062 if (InputUsed[OpNo] ==
Input) {
6065 }
else if (InputUsed[OpNo] == -1U) {
6067 InputUsed[OpNo] =
Input;
6072 if (OpNo >= std::size(InputUsed)) {
6075 UseBuildVector =
true;
6080 Ops.push_back(Idx + OpNo * NewElts);
6083 if (UseBuildVector) {
6088 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6090 int Idx = Mask[FirstMaskIdx + MaskOffset];
6095 if (
Input >= std::size(Inputs)) {
6102 Idx -=
Input * NewElts;
6106 .buildExtractVectorElement(
6107 EltTy, Inputs[
Input],
6113 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6114 }
else if (InputUsed[0] == -1U) {
6116 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6117 }
else if (NewElts == 1) {
6118 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6120 Register Op0 = Inputs[InputUsed[0]];
6124 : Inputs[InputUsed[1]];
6126 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6133 MI.eraseFromParent();
6146 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6152 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6155 const unsigned NumParts =
6157 : SrcTy.getNumElements();
6161 if (DstTy != NarrowTy)
6167 unsigned NumPartsLeft = NumParts;
6168 while (NumPartsLeft > 1) {
6169 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6172 .buildInstr(ScalarOpc, {NarrowTy},
6173 {SplitSrcs[Idx], SplitSrcs[Idx + 1]},
6177 SplitSrcs = PartialResults;
6178 PartialResults.
clear();
6179 NumPartsLeft = SplitSrcs.
size();
6183 MI.eraseFromParent();
6188 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6190 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]},
6194 MI.eraseFromParent();
6198 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6200 .buildInstr(RdxMI.getOpcode(), {DstTy},
6210 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6213 Register Acc = PartialReductions[0];
6214 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6215 if (Part == NumParts - 1) {
6216 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, {Acc, PartialReductions[Part]},
6220 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]},
6225 MI.eraseFromParent();
6231 unsigned int TypeIdx,
6233 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6234 MI.getFirst3RegLLTs();
6235 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6239 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6240 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6241 "Unexpected vecreduce opcode");
6242 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6243 ? TargetOpcode::G_FADD
6244 : TargetOpcode::G_FMUL;
6247 unsigned NumParts = SrcTy.getNumElements();
6250 for (
unsigned i = 0; i < NumParts; i++)
6252 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]},
6257 MI.eraseFromParent();
6264 unsigned ScalarOpc) {
6272 while (SplitSrcs.
size() > 1) {
6274 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6284 SplitSrcs = std::move(PartialRdxs);
6288 MI.getOperand(1).setReg(SplitSrcs[0]);
6295 const LLT HalfTy,
const LLT AmtTy) {
6297 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6298 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6302 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6303 MI.eraseFromParent();
6309 unsigned VTBits = 2 * NVTBits;
6312 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6313 if (Amt.
ugt(VTBits)) {
6315 }
else if (Amt.
ugt(NVTBits)) {
6318 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6319 }
else if (Amt == NVTBits) {
6327 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6330 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6331 if (Amt.
ugt(VTBits)) {
6333 }
else if (Amt.
ugt(NVTBits)) {
6335 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6337 }
else if (Amt == NVTBits) {
6341 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6343 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6345 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6351 if (Amt.
ugt(VTBits)) {
6353 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6354 }
else if (Amt.
ugt(NVTBits)) {
6356 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6358 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6359 }
else if (Amt == NVTBits) {
6362 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6364 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6366 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6368 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6375 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6376 MI.eraseFromParent();
6392 LLT DstTy = MRI.getType(DstReg);
6397 LLT ShiftAmtTy = MRI.getType(Amt);
6399 if (DstEltSize % 2 != 0)
6415 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6426 const unsigned NewBitSize = DstEltSize / 2;
6438 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6440 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6441 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6444 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6445 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6447 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6452 switch (
MI.getOpcode()) {
6453 case TargetOpcode::G_SHL: {
6455 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6457 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6458 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6459 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6462 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6463 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6465 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6467 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6469 ResultRegs[0] =
Lo.getReg(0);
6470 ResultRegs[1] =
Hi.getReg(0);
6473 case TargetOpcode::G_LSHR:
6474 case TargetOpcode::G_ASHR: {
6476 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6478 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6479 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6480 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6484 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6487 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6488 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6490 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6494 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6496 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6498 ResultRegs[0] =
Lo.getReg(0);
6499 ResultRegs[1] =
Hi.getReg(0);
6506 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6507 MI.eraseFromParent();
6516 LLT TargetTy,
LLT ShiftAmtTy) {
6519 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6521 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6522 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6523 const bool NeedsInterWordShift = ShiftBits != 0;
6526 case TargetOpcode::G_SHL: {
6529 if (PartIdx < ShiftWords)
6532 unsigned SrcIdx = PartIdx - ShiftWords;
6533 if (!NeedsInterWordShift)
6534 return SrcParts[SrcIdx];
6539 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6543 return Hi.getReg(0);
6546 case TargetOpcode::G_LSHR: {
6547 unsigned SrcIdx = PartIdx + ShiftWords;
6548 if (SrcIdx >= NumParts)
6550 if (!NeedsInterWordShift)
6551 return SrcParts[SrcIdx];
6555 if (SrcIdx + 1 < NumParts) {
6556 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6560 return Lo.getReg(0);
6563 case TargetOpcode::G_ASHR: {
6565 unsigned SrcIdx = PartIdx + ShiftWords;
6566 if (SrcIdx >= NumParts)
6568 if (!NeedsInterWordShift)
6569 return SrcParts[SrcIdx];
6574 (SrcIdx == NumParts - 1)
6578 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6600 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6601 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6606 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6615 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6616 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6618 auto IsZeroBitShift =
6626 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6627 : TargetOpcode::G_SHL;
6630 auto TargetBitsConst =
6632 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6637 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6642 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6644 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6648 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6661 LLT DstTy = MRI.getType(DstReg);
6665 const unsigned NumParts = DstBits / TargetBits;
6667 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6677 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6678 MI.eraseFromParent();
6683 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6684 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6690 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6694 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6697 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6698 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6702 for (
unsigned I = 0;
I < NumParts; ++
I)
6704 Params, TargetTy, ShiftAmtTy);
6706 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6707 MI.eraseFromParent();
6716 LLT DstTy = MRI.getType(DstReg);
6717 LLT ShiftAmtTy = MRI.getType(AmtReg);
6721 const unsigned NumParts = DstBits / TargetBits;
6723 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6740 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6752 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6753 auto TargetBitsLog2Const =
6754 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6755 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6758 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6760 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6768 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6769 auto TargetBitsMinusOneConst =
6770 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6772 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6773 TargetBitsMinusOneConst)
6776 FillValue = ZeroReg;
6784 for (
unsigned I = 0;
I < NumParts; ++
I) {
6786 Register InBoundsResult = FillValue;
6796 for (
unsigned K = 0;
K < NumParts; ++
K) {
6797 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy,
K);
6799 WordShift, WordShiftKConst);
6811 switch (
MI.getOpcode()) {
6812 case TargetOpcode::G_SHL:
6813 MainSrcIdx = (int)
I - (
int)
K;
6814 CarrySrcIdx = MainSrcIdx - 1;
6816 case TargetOpcode::G_LSHR:
6817 case TargetOpcode::G_ASHR:
6818 MainSrcIdx = (int)
I + (
int)
K;
6819 CarrySrcIdx = MainSrcIdx + 1;
6827 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6828 Register MainOp = SrcParts[MainSrcIdx];
6832 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6833 CarryOp = SrcParts[CarrySrcIdx];
6834 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6835 CarrySrcIdx >= (
int)NumParts)
6836 CarryOp = FillValue;
6842 ResultForK = FillValue;
6848 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6855 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6859 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6860 MI.eraseFromParent();
6867 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6870 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6885 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6890 "getNeutralElementForVecReduce called with invalid opcode!");
6891 case TargetOpcode::G_VECREDUCE_ADD:
6892 case TargetOpcode::G_VECREDUCE_OR:
6893 case TargetOpcode::G_VECREDUCE_XOR:
6894 case TargetOpcode::G_VECREDUCE_UMAX:
6896 case TargetOpcode::G_VECREDUCE_MUL:
6898 case TargetOpcode::G_VECREDUCE_AND:
6899 case TargetOpcode::G_VECREDUCE_UMIN:
6902 case TargetOpcode::G_VECREDUCE_SMAX:
6905 case TargetOpcode::G_VECREDUCE_SMIN:
6908 case TargetOpcode::G_VECREDUCE_FADD:
6910 case TargetOpcode::G_VECREDUCE_FMUL:
6912 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6913 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6914 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6915 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6923 unsigned Opc =
MI.getOpcode();
6925 case TargetOpcode::G_IMPLICIT_DEF:
6926 case TargetOpcode::G_LOAD: {
6934 case TargetOpcode::G_STORE:
6941 case TargetOpcode::G_AND:
6942 case TargetOpcode::G_OR:
6943 case TargetOpcode::G_XOR:
6944 case TargetOpcode::G_ADD:
6945 case TargetOpcode::G_SUB:
6946 case TargetOpcode::G_MUL:
6947 case TargetOpcode::G_FADD:
6948 case TargetOpcode::G_FSUB:
6949 case TargetOpcode::G_FMUL:
6950 case TargetOpcode::G_FDIV:
6951 case TargetOpcode::G_FCOPYSIGN:
6952 case TargetOpcode::G_UADDSAT:
6953 case TargetOpcode::G_USUBSAT:
6954 case TargetOpcode::G_SADDSAT:
6955 case TargetOpcode::G_SSUBSAT:
6956 case TargetOpcode::G_SMIN:
6957 case TargetOpcode::G_SMAX:
6958 case TargetOpcode::G_UMIN:
6959 case TargetOpcode::G_UMAX:
6960 case TargetOpcode::G_FMINNUM:
6961 case TargetOpcode::G_FMAXNUM:
6962 case TargetOpcode::G_FMINNUM_IEEE:
6963 case TargetOpcode::G_FMAXNUM_IEEE:
6964 case TargetOpcode::G_FMINIMUM:
6965 case TargetOpcode::G_FMAXIMUM:
6966 case TargetOpcode::G_FMINIMUMNUM:
6967 case TargetOpcode::G_FMAXIMUMNUM:
6968 case TargetOpcode::G_STRICT_FADD:
6969 case TargetOpcode::G_STRICT_FSUB:
6970 case TargetOpcode::G_STRICT_FMUL: {
6978 case TargetOpcode::G_SHL:
6979 case TargetOpcode::G_ASHR:
6980 case TargetOpcode::G_LSHR: {
6986 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6992 case TargetOpcode::G_FMA:
6993 case TargetOpcode::G_STRICT_FMA:
6994 case TargetOpcode::G_FSHR:
6995 case TargetOpcode::G_FSHL: {
7004 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
7005 case TargetOpcode::G_EXTRACT:
7012 case TargetOpcode::G_INSERT:
7013 case TargetOpcode::G_INSERT_VECTOR_ELT:
7014 case TargetOpcode::G_FREEZE:
7015 case TargetOpcode::G_FNEG:
7016 case TargetOpcode::G_FABS:
7017 case TargetOpcode::G_FSQRT:
7018 case TargetOpcode::G_FCEIL:
7019 case TargetOpcode::G_FFLOOR:
7020 case TargetOpcode::G_FNEARBYINT:
7021 case TargetOpcode::G_FRINT:
7022 case TargetOpcode::G_INTRINSIC_ROUND:
7023 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7024 case TargetOpcode::G_INTRINSIC_TRUNC:
7025 case TargetOpcode::G_BITREVERSE:
7026 case TargetOpcode::G_BSWAP:
7027 case TargetOpcode::G_FCANONICALIZE:
7028 case TargetOpcode::G_SEXT_INREG:
7029 case TargetOpcode::G_ABS:
7030 case TargetOpcode::G_CTLZ:
7031 case TargetOpcode::G_CTPOP:
7039 case TargetOpcode::G_SELECT: {
7040 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7042 if (!CondTy.isScalar() ||
7048 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7050 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7055 if (CondTy.isVector())
7065 case TargetOpcode::G_UNMERGE_VALUES:
7067 case TargetOpcode::G_PHI:
7069 case TargetOpcode::G_SHUFFLE_VECTOR:
7071 case TargetOpcode::G_BUILD_VECTOR: {
7073 for (
auto Op :
MI.uses()) {
7081 MIRBuilder.buildDeleteTrailingVectorElements(
7082 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7083 MI.eraseFromParent();
7086 case TargetOpcode::G_SEXT:
7087 case TargetOpcode::G_ZEXT:
7088 case TargetOpcode::G_ANYEXT:
7089 case TargetOpcode::G_TRUNC:
7090 case TargetOpcode::G_FPTRUNC:
7091 case TargetOpcode::G_FPEXT:
7092 case TargetOpcode::G_FPTOSI:
7093 case TargetOpcode::G_FPTOUI:
7094 case TargetOpcode::G_FPTOSI_SAT:
7095 case TargetOpcode::G_FPTOUI_SAT:
7096 case TargetOpcode::G_SITOFP:
7097 case TargetOpcode::G_UITOFP:
7098 case TargetOpcode::G_TRUNC_SSAT_S:
7099 case TargetOpcode::G_TRUNC_SSAT_U:
7100 case TargetOpcode::G_TRUNC_USAT_U: {
7107 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7110 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7118 case TargetOpcode::G_ICMP:
7119 case TargetOpcode::G_FCMP: {
7127 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7132 case TargetOpcode::G_BITCAST: {
7136 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7137 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7153 case TargetOpcode::G_VECREDUCE_FADD:
7154 case TargetOpcode::G_VECREDUCE_FMUL:
7155 case TargetOpcode::G_VECREDUCE_ADD:
7156 case TargetOpcode::G_VECREDUCE_MUL:
7157 case TargetOpcode::G_VECREDUCE_AND:
7158 case TargetOpcode::G_VECREDUCE_OR:
7159 case TargetOpcode::G_VECREDUCE_XOR:
7160 case TargetOpcode::G_VECREDUCE_SMAX:
7161 case TargetOpcode::G_VECREDUCE_SMIN:
7162 case TargetOpcode::G_VECREDUCE_UMAX:
7163 case TargetOpcode::G_VECREDUCE_UMIN: {
7164 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7166 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7167 auto NeutralElement = getNeutralElementForVecReduce(
7173 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7174 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7175 NeutralElement, Idx);
7179 MO.
setReg(NewVec.getReg(0));
7191 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7193 unsigned MaskNumElts = Mask.size();
7194 unsigned SrcNumElts = SrcTy.getNumElements();
7197 if (MaskNumElts == SrcNumElts)
7200 if (MaskNumElts < SrcNumElts) {
7208 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7209 MI.getOperand(1).getReg(),
7210 MI.getOperand(2).getReg(), NewMask);
7211 MI.eraseFromParent();
7216 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7217 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7226 MOps1[0] =
MI.getOperand(1).getReg();
7227 MOps2[0] =
MI.getOperand(2).getReg();
7229 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7230 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7234 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7236 if (Idx >=
static_cast<int>(SrcNumElts))
7237 Idx += PaddedMaskNumElts - SrcNumElts;
7242 if (MaskNumElts != PaddedMaskNumElts) {
7244 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7247 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7249 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7254 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7257 MI.eraseFromParent();
7263 unsigned int TypeIdx,
LLT MoreTy) {
7264 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7266 unsigned NumElts = DstTy.getNumElements();
7269 if (DstTy.isVector() && Src1Ty.isVector() &&
7270 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7278 if (DstTy != Src1Ty || DstTy != Src2Ty)
7286 for (
unsigned I = 0;
I != NumElts; ++
I) {
7288 if (Idx <
static_cast<int>(NumElts))
7291 NewMask[
I] = Idx - NumElts + WidenNumElts;
7295 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7296 MI.getOperand(1).getReg(),
7297 MI.getOperand(2).getReg(), NewMask);
7298 MI.eraseFromParent();
7307 unsigned SrcParts = Src1Regs.
size();
7308 unsigned DstParts = DstRegs.
size();
7310 unsigned DstIdx = 0;
7312 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7313 DstRegs[DstIdx] = FactorSum;
7318 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7320 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7321 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7323 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7329 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7330 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7331 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7332 unsigned i = RevI - 1;
7334 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7344 if (DstIdx != DstParts - 1) {
7345 MachineInstrBuilder Uaddo =
7346 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7347 FactorSum = Uaddo.
getReg(0);
7348 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7349 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7350 MachineInstrBuilder Uaddo =
7351 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7352 FactorSum = Uaddo.
getReg(0);
7353 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7354 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7358 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7359 for (
unsigned i = 2; i < Factors.
size(); ++i)
7360 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7363 CarrySumPrevDstIdx = CarrySum;
7364 DstRegs[DstIdx] = FactorSum;
7376 LLT DstType = MRI.getType(DstReg);
7378 if (DstType.isVector())
7381 unsigned Opcode =
MI.getOpcode();
7382 unsigned OpO, OpE, OpF;
7384 case TargetOpcode::G_SADDO:
7385 case TargetOpcode::G_SADDE:
7386 case TargetOpcode::G_UADDO:
7387 case TargetOpcode::G_UADDE:
7388 case TargetOpcode::G_ADD:
7389 OpO = TargetOpcode::G_UADDO;
7390 OpE = TargetOpcode::G_UADDE;
7391 OpF = TargetOpcode::G_UADDE;
7392 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7393 OpF = TargetOpcode::G_SADDE;
7395 case TargetOpcode::G_SSUBO:
7396 case TargetOpcode::G_SSUBE:
7397 case TargetOpcode::G_USUBO:
7398 case TargetOpcode::G_USUBE:
7399 case TargetOpcode::G_SUB:
7400 OpO = TargetOpcode::G_USUBO;
7401 OpE = TargetOpcode::G_USUBE;
7402 OpF = TargetOpcode::G_USUBE;
7403 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7404 OpF = TargetOpcode::G_SSUBE;
7411 unsigned NumDefs =
MI.getNumExplicitDefs();
7412 Register Src1 =
MI.getOperand(NumDefs).getReg();
7413 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7416 CarryDst =
MI.getOperand(1).getReg();
7417 if (
MI.getNumOperands() == NumDefs + 3)
7418 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7420 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7421 LLT LeftoverTy, DummyTy;
7423 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7428 int NarrowParts = Src1Regs.
size();
7429 Src1Regs.
append(Src1Left);
7430 Src2Regs.
append(Src2Left);
7433 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7435 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7438 if (i == e - 1 && CarryDst)
7439 CarryOut = CarryDst;
7441 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7444 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7445 {Src1Regs[i], Src2Regs[i]});
7446 }
else if (i == e - 1) {
7447 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7448 {Src1Regs[i], Src2Regs[i], CarryIn});
7450 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7451 {Src1Regs[i], Src2Regs[i], CarryIn});
7457 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7458 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7459 ArrayRef(DstRegs).drop_front(NarrowParts));
7461 MI.eraseFromParent();
7467 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7469 LLT Ty = MRI.getType(DstReg);
7473 unsigned Size = Ty.getSizeInBits();
7475 if (
Size % NarrowSize != 0)
7478 unsigned NumParts =
Size / NarrowSize;
7479 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7480 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7486 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7490 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7491 MI.eraseFromParent();
7501 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7504 LLT SrcTy = MRI.getType(Src);
7516 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7529 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7532 if (SizeOp1 % NarrowSize != 0)
7534 int NumParts = SizeOp1 / NarrowSize;
7537 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7541 uint64_t OpStart =
MI.getOperand(2).getImm();
7542 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7543 for (
int i = 0; i < NumParts; ++i) {
7544 unsigned SrcStart = i * NarrowSize;
7546 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7549 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7557 int64_t ExtractOffset;
7559 if (OpStart < SrcStart) {
7561 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7563 ExtractOffset = OpStart - SrcStart;
7564 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7568 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7570 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7571 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7578 if (MRI.getType(DstReg).isVector())
7579 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7580 else if (DstRegs.
size() > 1)
7581 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7584 MI.eraseFromParent();
7596 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7598 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7601 SrcRegs.
append(LeftoverRegs);
7605 uint64_t OpStart =
MI.getOperand(3).getImm();
7606 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7607 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7608 unsigned DstStart =
I * NarrowSize;
7610 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7618 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7620 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7624 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7632 int64_t ExtractOffset, InsertOffset;
7634 if (OpStart < DstStart) {
7636 ExtractOffset = DstStart - OpStart;
7637 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7639 InsertOffset = OpStart - DstStart;
7641 SegSize = std::min(NarrowSize - InsertOffset, OpSize);
7645 if (ExtractOffset != 0 || SegSize != OpSize) {
7647 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7648 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7651 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7652 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7656 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7660 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7663 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7665 MI.eraseFromParent();
7673 LLT DstTy = MRI.getType(DstReg);
7675 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7681 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7682 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7686 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7687 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7690 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7691 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7692 {Src0Regs[I], Src1Regs[I]});
7696 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7699 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7700 DstLeftoverRegs.
push_back(Inst.getReg(0));
7703 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7704 LeftoverTy, DstLeftoverRegs);
7706 MI.eraseFromParent();
7716 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7718 LLT DstTy = MRI.getType(DstReg);
7723 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7724 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7725 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7727 MI.eraseFromParent();
7737 Register CondReg =
MI.getOperand(1).getReg();
7738 LLT CondTy = MRI.getType(CondReg);
7739 if (CondTy.isVector())
7743 LLT DstTy = MRI.getType(DstReg);
7749 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7750 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7754 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7755 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7758 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7760 CondReg, Src1Regs[
I], Src2Regs[
I]);
7764 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7766 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7770 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7771 LeftoverTy, DstLeftoverRegs);
7773 MI.eraseFromParent();
7783 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7786 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7787 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7790 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7792 auto C_0 =
B.buildConstant(NarrowTy, 0);
7794 UnmergeSrc.getReg(1), C_0);
7795 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7796 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7797 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7798 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7799 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7800 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7802 MI.eraseFromParent();
7815 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7818 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7819 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7822 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7824 auto C_0 =
B.buildConstant(NarrowTy, 0);
7826 UnmergeSrc.getReg(0), C_0);
7827 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7828 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7829 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7830 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7831 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7832 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7834 MI.eraseFromParent();
7847 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7850 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7855 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7859 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7860 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7868 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7869 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7872 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7873 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7875 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7877 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7879 MI.eraseFromParent();
7889 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7892 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7893 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7895 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7896 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7897 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7899 MI.eraseFromParent();
7914 LLT ExpTy = MRI.getType(ExpReg);
7919 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7920 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7921 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7922 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7924 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7926 MI.getOperand(2).setReg(Trunc.getReg(0));
7933 unsigned Opc =
MI.getOpcode();
7936 auto QAction = LI.getAction(Q).Action;
7942 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7945 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7949 case TargetOpcode::G_CTLZ: {
7950 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7951 unsigned Len = SrcTy.getScalarSizeInBits();
7953 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7955 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7956 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7959 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7960 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7961 MI.eraseFromParent();
7977 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7978 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7981 Op = MIBOp.getReg(0);
7986 MI.eraseFromParent();
7989 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7992 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7996 case TargetOpcode::G_CTTZ: {
7997 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7999 unsigned Len = SrcTy.getScalarSizeInBits();
8000 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
8003 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
8004 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
8007 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8008 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
8009 MI.eraseFromParent();
8016 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8017 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8019 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8020 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8021 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8022 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8025 MI.eraseFromParent();
8029 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8030 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8034 case TargetOpcode::G_CTPOP: {
8036 LLT Ty = MRI.getType(SrcReg);
8037 unsigned Size = Ty.getScalarSizeInBits();
8049 auto C_1 =
B.buildConstant(Ty, 1);
8050 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8052 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8053 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8054 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8058 auto C_2 =
B.buildConstant(Ty, 2);
8059 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8061 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8062 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8063 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8064 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8071 auto C_4 =
B.buildConstant(Ty, 4);
8072 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8073 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8075 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8076 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8078 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8081 if (
Size == 16 && !Ty.isVector()) {
8083 auto C_8 =
B.buildConstant(Ty, 8);
8084 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8085 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8086 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8087 MI.eraseFromParent();
8096 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8098 auto IsMulSupported = [
this](
const LLT Ty) {
8099 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8102 if (IsMulSupported(Ty)) {
8103 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8104 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8106 auto ResTmp = B8Count;
8107 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8108 auto ShiftC =
B.buildConstant(Ty, Shift);
8109 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8110 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8112 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8114 MI.eraseFromParent();
8117 case TargetOpcode::G_CTLS: {
8118 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8122 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8123 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8125 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8131 MI.eraseFromParent();
8152 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8153 LLT Ty = MRI.getType(Dst);
8154 LLT ShTy = MRI.getType(Z);
8161 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8162 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8167 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8168 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8172 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8185 MI.eraseFromParent();
8191 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8192 LLT Ty = MRI.getType(Dst);
8193 LLT ShTy = MRI.getType(Z);
8196 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8206 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8207 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8208 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8209 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8210 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8214 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8217 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8220 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8222 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8223 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8224 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8227 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8229 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8231 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8234 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8235 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8240 MI.eraseFromParent();
8251 LLT Ty = MRI.getType(Dst);
8252 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8254 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8255 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8258 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8259 return lowerFunnelShiftAsShifts(
MI);
8263 if (Result == UnableToLegalize)
8264 return lowerFunnelShiftAsShifts(
MI);
8269 auto [Dst, Src] =
MI.getFirst2Regs();
8270 LLT DstTy = MRI.getType(Dst);
8271 LLT SrcTy = MRI.getType(Src);
8275 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8283 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8287 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8291 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8296 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8297 {UnmergeSrc.getReg(0)});
8298 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8299 {UnmergeSrc.getReg(1)});
8302 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8304 MI.eraseFromParent();
8321 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8325 LLT DstTy = MRI.getType(DstReg);
8326 LLT SrcTy = MRI.getType(SrcReg);
8334 SrcTy.getElementCount().divideCoefficientBy(2));
8347 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8359 MI.eraseFromParent();
8368 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8369 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8370 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8371 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8372 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8373 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8374 MI.eraseFromParent();
8379 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8381 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8382 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8387 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8388 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8390 return lowerRotateWithReverseRotate(
MI);
8393 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8394 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8395 bool IsFShLegal =
false;
8396 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8397 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8401 MI.eraseFromParent();
8406 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8409 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8414 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8415 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8416 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8422 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8423 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8425 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8431 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8432 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8434 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8436 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8441 MI.eraseFromParent();
8449 auto [Dst, Src] =
MI.getFirst2Regs();
8454 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8467 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8469 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8474 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8476 MI.eraseFromParent();
8484 auto [Dst, Src] =
MI.getFirst2Regs();
8488 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8499 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8500 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8502 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8509 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8510 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8511 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8513 MI.eraseFromParent();
8524 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8525 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8531 MI.eraseFromParent();
8536 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8539 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8540 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8541 MIRBuilder.buildSelect(Dst, Src, True, False);
8542 MI.eraseFromParent();
8546 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8566 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8573 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8574 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8575 MIRBuilder.buildSelect(Dst, Src, True, False);
8576 MI.eraseFromParent();
8580 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8586 if (DstTy.getScalarSizeInBits() == 32) {
8593 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8594 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8596 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8603 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8604 MI.eraseFromParent();
8612 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8616 if (SrcTy !=
S64 && SrcTy !=
S32)
8618 if (DstTy !=
S32 && DstTy !=
S64)
8645 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8647 MI.eraseFromParent();
8652 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8657 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8664 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8666 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8667 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8669 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8670 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8672 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8674 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8675 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8676 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8679 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8680 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8681 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8683 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask,
K);
8686 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8691 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8692 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8698 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8700 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8701 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8703 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8708 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8709 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8711 MI.eraseFromParent();
8717 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8719 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8720 unsigned SatWidth = DstTy.getScalarSizeInBits();
8724 APInt MinInt, MaxInt;
8747 if (AreExactFloatBounds) {
8749 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8752 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8754 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8763 MI.eraseFromParent();
8768 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8773 MI.eraseFromParent();
8780 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8788 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8798 MI.eraseFromParent();
8804 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8808 MI.eraseFromParent();
8815 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8816 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8817 "Only G_FPEXT and G_FPTRUNC are expected");
8819 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8824 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8826 StoreOpc = TargetOpcode::G_STORE;
8827 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8830 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8831 LoadOpc = TargetOpcode::G_LOAD;
8840 StackTy, StackTyAlign);
8841 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8844 StackTy, StackTyAlign);
8845 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8847 MI.eraseFromParent();
8855 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8856 assert(SrcTy.getScalarType().isBFloat16() &&
8857 "expected a bf16 source for bf16 fpext lowering");
8868 if (DstTy.getScalarType().isFloat32())
8873 MI.eraseFromParent();
8878 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8879 if (SrcTy.getScalarType().isBFloat16() &&
8880 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8892 auto [Dst, Src] =
MI.getFirst2Regs();
8896 if (MRI.getType(Src).isVector())
8900 unsigned Flags =
MI.getFlags();
8903 MI.eraseFromParent();
8907 const unsigned ExpMask = 0x7ff;
8908 const unsigned ExpBiasf64 = 1023;
8909 const unsigned ExpBiasf16 = 15;
8911 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8921 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8928 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8930 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8932 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8936 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8938 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8940 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8941 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8949 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8950 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
8961 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
8972 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
8988 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
8998 MI.eraseFromParent();
9005 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9013 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9039 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9041 MI.eraseFromParent();
9050 LLT OperandTy = MRI.getType(
Op);
9060 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9062 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9063 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9064 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9065 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9066 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9074 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9077 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9079 AbsWide, AbsNarrowAsWide);
9083 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9084 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9086 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9087 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9093 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9099 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9100 MI.eraseFromParent();
9106 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9107 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9110 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9113 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9120 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9121 LLT Ty = MRI.getType(Dst);
9123 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9124 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9125 MI.eraseFromParent();
9130 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9131 LLT Ty = MRI.getType(Src);
9132 auto Flags =
MI.getFlags();
9140 FracToUse = FracPart.getReg(0);
9142 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9146 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9148 FracToUse =
Select.getReg(0);
9151 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9154 MI.eraseFromParent();
9160 case TargetOpcode::G_SMIN:
9162 case TargetOpcode::G_SMAX:
9164 case TargetOpcode::G_UMIN:
9166 case TargetOpcode::G_UMAX:
9174 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9179 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9180 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9182 MI.eraseFromParent();
9191 LLT DstTy = MRI.getType(Dst);
9192 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9202 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9203 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9205 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9208 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9209 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9210 if (TLI.preferSelectsOverBooleanArithmetic(
9213 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9214 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9216 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9217 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9223 unsigned BoolExtOp =
9225 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9226 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9230 MI.eraseFromParent();
9236 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9237 const int Src0Size = Src0Ty.getScalarSizeInBits();
9238 const int Src1Size = Src1Ty.getScalarSizeInBits();
9248 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9249 Src0Ty.getScalarType().isInteger()))
9250 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9252 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9253 Src1Ty.getScalarType().isInteger()))
9254 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9259 auto NotSignBitMask =
MIRBuilder.buildConstant(
9263 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9265 if (Src0Ty == Src1Ty) {
9266 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9267 }
else if (Src0Size > Src1Size) {
9268 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9269 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9270 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9271 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9273 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9274 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9275 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9276 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9282 unsigned Flags =
MI.getFlags();
9287 if (DstTy == DstIntTy)
9288 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9294 MI.eraseFromParent();
9305 switch (
MI.getOpcode()) {
9306 case TargetOpcode::G_FMINNUM:
9307 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9309 case TargetOpcode::G_FMINIMUMNUM:
9310 NewOp = TargetOpcode::G_FMINNUM;
9312 case TargetOpcode::G_FMAXNUM:
9313 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9315 case TargetOpcode::G_FMAXIMUMNUM:
9316 NewOp = TargetOpcode::G_FMAXNUM;
9322 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9323 LLT Ty = MRI.getType(Dst);
9332 if (!VT->isKnownNeverSNaN(Src0))
9333 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9335 if (!VT->isKnownNeverSNaN(Src1))
9336 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9341 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9342 MI.eraseFromParent();
9348 unsigned Opc =
MI.getOpcode();
9349 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9350 LLT Ty = MRI.getType(Dst);
9353 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9355 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9356 unsigned OpcNonIeee =
9357 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9358 bool MinMaxMustRespectOrderedZero =
false;
9362 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9364 MinMaxMustRespectOrderedZero =
true;
9365 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9370 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9375 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9378 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9382 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9384 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9394 const unsigned Flags =
MI.getFlags();
9400 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9402 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9404 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9406 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9408 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9413 MI.eraseFromParent();
9420 LLT Ty = MRI.getType(DstReg);
9421 unsigned Flags =
MI.getFlags();
9426 MI.eraseFromParent();
9432 auto [DstReg,
X] =
MI.getFirst2Regs();
9433 const unsigned Flags =
MI.getFlags();
9434 const LLT Ty = MRI.getType(DstReg);
9446 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9448 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9453 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9454 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9455 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9456 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9458 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9460 MI.eraseFromParent();
9465 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9466 unsigned Flags =
MI.getFlags();
9467 LLT Ty = MRI.getType(DstReg);
9474 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9475 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9478 SrcReg, Zero, Flags);
9480 SrcReg, Trunc, Flags);
9484 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9485 MI.eraseFromParent();
9491 const unsigned NumOps =
MI.getNumOperands();
9492 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9493 unsigned PartSize = Src0Ty.getSizeInBits();
9498 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9499 const unsigned Offset = (
I - 1) * PartSize;
9502 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9505 MRI.createGenericVirtualRegister(WideTy);
9508 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9509 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9510 ResultReg = NextResult;
9513 if (DstTy.isPointer()) {
9514 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9515 DstTy.getAddressSpace())) {
9521 }
else if (WideTy != DstTy) {
9525 MI.eraseFromParent();
9531 const unsigned NumDst =
MI.getNumOperands() - 1;
9532 Register SrcReg =
MI.getOperand(NumDst).getReg();
9533 Register Dst0Reg =
MI.getOperand(0).getReg();
9534 LLT DstTy = MRI.getType(Dst0Reg);
9543 LLT IntTy = MRI.getType(SrcReg);
9548 unsigned Offset = DstSize;
9549 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9551 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9555 MI.eraseFromParent();
9574 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9575 InsertVal =
MI.getOperand(2).getReg();
9577 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9579 LLT VecTy = MRI.getType(SrcVec);
9589 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9590 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9592 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9595 MI.eraseFromParent();
9600 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9611 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9618 int64_t
Offset = IdxVal * EltBytes;
9629 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9632 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9634 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9637 MI.eraseFromParent();
9643 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9644 MI.getFirst3RegLLTs();
9654 for (
int Idx : Mask) {
9656 if (!
Undef.isValid())
9662 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9664 int NumElts = Src0Ty.getNumElements();
9665 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9666 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9667 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9669 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9671 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9676 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9677 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9678 MI.eraseFromParent();
9684 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9685 MI.getFirst4RegLLTs();
9687 if (VecTy.isScalableVector())
9703 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9708 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9711 std::optional<APInt> PassthruSplatVal =
9714 if (PassthruSplatVal.has_value()) {
9716 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9717 }
else if (HasPassthru) {
9718 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9719 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9725 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9729 unsigned NumElmts = VecTy.getNumElements();
9730 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9732 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9735 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9738 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9743 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9745 if (HasPassthru &&
I == NumElmts - 1) {
9748 auto AllLanesSelected =
MIRBuilder.buildICmp(
9750 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9751 {OutPos, EndOfVector});
9755 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9757 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9762 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9764 MI.eraseFromParent();
9781 if (Alignment >
Align(1)) {
9782 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9793 const auto &MF = *
MI.getMF();
9799 Register AllocSize =
MI.getOperand(1).getReg();
9802 LLT PtrTy = MRI.getType(Dst);
9803 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9810 MI.eraseFromParent();
9816 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9821 MI.eraseFromParent();
9827 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9832 MI.eraseFromParent();
9838 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9839 unsigned Offset =
MI.getOperand(2).getImm();
9842 if (SrcTy.isVector()) {
9843 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9844 unsigned DstSize = DstTy.getSizeInBits();
9846 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9847 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9849 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9853 for (
unsigned Idx =
Offset / SrcEltSize;
9854 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9855 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9857 if (SubVectorElts.
size() == 1)
9858 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9860 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9862 MI.eraseFromParent();
9868 if ((SrcTy.isPointer() &&
9869 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9870 (DstTy.isPointer() &&
9871 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9872 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9876 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9877 (SrcTy.isScalar() || SrcTy.isPointer() ||
9878 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9879 LLT SrcIntTy = SrcTy;
9880 if (!SrcTy.isScalar()) {
9882 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9886 if (DstTy.isPointer())
9888 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9894 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9898 if (DstTy.isPointer())
9901 MI.eraseFromParent();
9909 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9910 uint64_t
Offset =
MI.getOperand(3).getImm();
9912 LLT DstTy = MRI.getType(Src);
9913 LLT InsertTy = MRI.getType(InsertSrc);
9916 bool IsNonIntegralInsert =
9926 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9927 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9934 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9936 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9940 for (; Idx <
Offset / EltSize; ++Idx) {
9941 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9946 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9947 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9949 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9953 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
9955 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
9962 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9965 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9966 MI.eraseFromParent();
9975 if (IsNonIntegralDst || IsNonIntegralInsert) {
9976 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9980 LLT IntDstTy = DstTy;
9984 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9989 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9995 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10001 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10002 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10003 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10006 MI.eraseFromParent();
10012 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10013 MI.getFirst4RegLLTs();
10014 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10017 LLT BoolTy = Dst1Ty;
10019 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10028 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10034 auto ResultLowerThanLHS =
10038 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10042 auto LHSLessThanRHS =
10044 auto ResultNegative =
10046 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10050 MI.eraseFromParent();
10056 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10057 const LLT Ty = MRI.getType(Res);
10060 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10061 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10062 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10066 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10067 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10070 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10073 MI.eraseFromParent();
10078 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10079 const LLT Ty = MRI.getType(Res);
10082 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10083 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10084 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10088 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10089 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10091 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10094 MI.eraseFromParent();
10100 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10101 LLT Ty = MRI.getType(Res);
10105 switch (
MI.getOpcode()) {
10108 case TargetOpcode::G_UADDSAT:
10111 BaseOp = TargetOpcode::G_ADD;
10113 case TargetOpcode::G_SADDSAT:
10116 BaseOp = TargetOpcode::G_ADD;
10118 case TargetOpcode::G_USUBSAT:
10121 BaseOp = TargetOpcode::G_SUB;
10123 case TargetOpcode::G_SSUBSAT:
10126 BaseOp = TargetOpcode::G_SUB;
10141 uint64_t NumBits = Ty.getScalarSizeInBits();
10148 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10152 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10160 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10165 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10166 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10169 MI.eraseFromParent();
10175 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10176 LLT Ty = MRI.getType(Res);
10180 unsigned OverflowOp;
10181 switch (
MI.getOpcode()) {
10184 case TargetOpcode::G_UADDSAT:
10187 OverflowOp = TargetOpcode::G_UADDO;
10189 case TargetOpcode::G_SADDSAT:
10192 OverflowOp = TargetOpcode::G_SADDO;
10194 case TargetOpcode::G_USUBSAT:
10197 OverflowOp = TargetOpcode::G_USUBO;
10199 case TargetOpcode::G_SSUBSAT:
10202 OverflowOp = TargetOpcode::G_SSUBO;
10207 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10208 Register Tmp = OverflowRes.getReg(0);
10209 Register Ov = OverflowRes.getReg(1);
10218 uint64_t NumBits = Ty.getScalarSizeInBits();
10219 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10220 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10223 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10231 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10233 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10235 MI.eraseFromParent();
10241 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10242 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10243 "Expected shlsat opcode!");
10244 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10245 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10246 LLT Ty = MRI.getType(Res);
10250 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10251 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10260 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10265 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10267 MI.eraseFromParent();
10273 unsigned Opc =
MI.getOpcode();
10274 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10275 unsigned DstSize = DstTy.getScalarSizeInBits();
10276 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10278 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10281 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10284 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10285 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10288 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10289 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10292 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10294 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10300 MI.eraseFromParent();
10305 auto [Dst, Src] =
MI.getFirst2Regs();
10306 const LLT Ty = MRI.getType(Src);
10307 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10308 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10311 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10312 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10313 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10314 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10317 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10320 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10321 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10323 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10324 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10325 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10327 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10328 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10329 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10331 Res.getInstr()->getOperand(0).setReg(Dst);
10333 MI.eraseFromParent();
10340 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10343 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10344 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10345 return B.buildOr(Dst,
LHS,
RHS);
10350 auto [Dst, Src] =
MI.getFirst2Regs();
10351 const LLT SrcTy = MRI.getType(Src);
10352 unsigned Size = SrcTy.getScalarSizeInBits();
10353 unsigned VSize = SrcTy.getSizeInBits();
10356 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10357 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10358 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10359 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10364 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10365 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10366 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10370 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10393 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10397 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10400 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10404 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10408 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10413 MI.eraseFromParent();
10421 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10422 int NameOpIdx = IsRead ? 1 : 0;
10423 int ValRegIndex = IsRead ? 0 : 1;
10425 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10426 const LLT Ty = MRI.getType(ValReg);
10428 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10435 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10436 Fn,
MI.getDebugLoc()));
10440 MI.eraseFromParent();
10449 MI.eraseFromParent();
10455 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10456 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10457 Register Result =
MI.getOperand(0).getReg();
10458 LLT OrigTy = MRI.getType(Result);
10462 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10463 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10465 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10467 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10468 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10471 MI.eraseFromParent();
10477 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10482 MI.eraseFromParent();
10487 MI.eraseFromParent();
10494 unsigned BitSize = SrcTy.getScalarSizeInBits();
10498 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10505 APInt ExpMask = Inf;
10507 APInt QNaNBitMask =
10511 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10512 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10513 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10514 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10515 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10517 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10521 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10523 LLT DstTyCopy = DstTy;
10525 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10553 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10556 Mask &= ~PartialCheck;
10565 else if (PartialCheck ==
fcZero)
10577 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10578 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10579 auto SubnormalRes =
10581 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10583 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10584 appendToRes(SubnormalRes);
10591 else if (PartialCheck ==
fcInf)
10596 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10603 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10604 if (PartialCheck ==
fcNan) {
10608 }
else if (PartialCheck ==
fcQNan) {
10618 Abs, InfWithQnanBitC);
10619 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10626 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10628 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10629 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10632 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10634 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10637 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10638 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10640 appendToRes(NormalRes);
10644 MI.eraseFromParent();
10650 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10651 MI.getFirst4RegLLTs();
10660 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10661 Op1Ty = MRI.getType(Op1Reg);
10662 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10663 Op2Ty = MRI.getType(Op2Reg);
10667 if (MaskTy.isScalar()) {
10675 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10678 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10680 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10682 if (DstTy.isVector()) {
10684 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10685 MaskReg = ShufSplat.getReg(0);
10689 }
else if (!DstTy.isVector()) {
10694 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10698 if (!Op1Ty.getScalarType().isAnyScalar() &&
10699 !Op1Ty.getScalarType().isInteger())
10700 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10702 if (!Op2Ty.getScalarType().isAnyScalar() &&
10703 !Op2Ty.getScalarType().isInteger()) {
10705 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10706 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10709 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10710 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10711 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10716 if (DstTy == Op1TyInt)
10719 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10723 MI.eraseFromParent();
10729 unsigned Opcode =
MI.getOpcode();
10732 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10733 : TargetOpcode::G_UDIV,
10734 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10736 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10737 : TargetOpcode::G_UREM,
10738 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10739 MI.eraseFromParent();
10749 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10753 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10756 MI.eraseFromParent();
10766 Register SrcReg =
MI.getOperand(1).getReg();
10767 LLT Ty = MRI.getType(SrcReg);
10768 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10771 MI.eraseFromParent();
10777 Register SrcReg =
MI.getOperand(1).getReg();
10778 Register DestReg =
MI.getOperand(0).getReg();
10780 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10781 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10784 MI.eraseFromParent();
10790 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10791 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10792 "Expected G_ABDS or G_ABDU instruction");
10794 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10795 LLT Ty = MRI.getType(LHS);
10805 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10807 MI.eraseFromParent();
10813 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10814 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10815 "Expected G_ABDS or G_ABDU instruction");
10817 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10818 LLT Ty = MRI.getType(LHS);
10823 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10824 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10825 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10827 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10828 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10830 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10832 MI.eraseFromParent();
10837 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10842 if (!(SrcTy.getScalarType().isAnyScalar() ||
10843 SrcTy.getScalarType().isInteger())) {
10845 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10846 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10849 if (MRI.getType(DstReg) != TyInt) {
10853 .buildAnd(TyInt, CastedSrc,
10856 DstTy.getScalarSizeInBits())))
10868 MI.eraseFromParent();
10874 Register SrcReg =
MI.getOperand(1).getReg();
10875 LLT SrcTy = MRI.getType(SrcReg);
10876 LLT DstTy = MRI.getType(SrcReg);
10879 if (SrcTy.isScalar()) {
10884 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10895 Register ListPtr =
MI.getOperand(1).getReg();
10896 LLT PtrTy = MRI.getType(ListPtr);
10903 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10905 const Align A(
MI.getOperand(2).getImm());
10907 if (
A > TLI.getMinStackArgumentAlignment()) {
10909 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10910 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10911 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10912 VAList = AndDst.getReg(0);
10919 LLT LLTTy = MRI.getType(Dst);
10922 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10923 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10928 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10930 Align EltAlignment =
DL.getABITypeAlign(Ty);
10933 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10935 MI.eraseFromParent();
10940 unsigned OpCode =
MI.getOpcode();
10941 assert((OpCode == TargetOpcode::G_SMULFIX ||
10942 OpCode == TargetOpcode::G_UMULFIX ||
10943 OpCode == TargetOpcode::G_SMULFIXSAT ||
10944 OpCode == TargetOpcode::G_UMULFIXSAT) &&
10945 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
10946 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10947 LLT Ty = MRI.getType(Dst);
10948 unsigned Scale =
MI.getOperand(3).getImm();
10950 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
10951 OpCode == TargetOpcode::G_UMULFIXSAT);
10952 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
10953 OpCode == TargetOpcode::G_SMULFIXSAT);
10955 if (!Saturating && Scale == 0) {
10957 MI.eraseFromParent();
10963 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
10986 MI.eraseFromParent();
10993 unsigned NumBits = Ty.getScalarSizeInBits();
10995 if (!Ty.isVector() && ValVRegAndVal) {
10996 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
11004 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11027 auto &MF = *
MI.getParent()->getParent();
11032 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11033 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11036 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11037 const auto &DstMMO = **
MI.memoperands_begin();
11039 if (DstAlignCanChange) {
11042 Align NewAlign =
DL.getABITypeAlign(IRTy);
11043 if (NewAlign > Alignment) {
11052 MachineIRBuilder MIB(
MI);
11054 LLT LargestTy = MemOps[0];
11055 for (
unsigned i = 1; i < MemOps.
size(); i++)
11057 LargestTy = MemOps[i];
11069 LLT PtrTy = MRI.getType(Dst);
11070 unsigned DstOff = 0;
11071 unsigned Size = KnownLen;
11072 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11073 LLT Ty = MemOps[
I];
11076 if (TySize >
Size) {
11080 DstOff -= TySize -
Size;
11090 TLI.isTruncateFree(LargestVT, VT))
11091 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11104 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11107 MIB.buildStore(
Value, Ptr, *StoreMMO);
11112 MI.eraseFromParent();
11120 auto &MF = *
MI.getParent()->getParent();
11124 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11125 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11128 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11134 const auto &DstMMO = **
MI.memoperands_begin();
11135 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11137 if (DstAlignCanChange) {
11140 Align NewAlign =
DL.getABITypeAlign(IRTy);
11145 if (!
TRI->hasStackRealignment(MF))
11146 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11147 NewAlign = std::min(NewAlign, *StackAlign);
11149 if (NewAlign > Alignment) {
11158 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11160 MachineIRBuilder MIB(
MI);
11166 unsigned CurrOffset = 0;
11167 unsigned Size = KnownLen;
11168 for (
auto CopyTy : MemOps) {
11169 TypeSize TySize = CopyTy.getSizeInBytes();
11173 if (TySize >
Size) {
11174 unsigned Overlap = TySize -
Size;
11175 assert(Overlap < CurrOffset &&
11176 "overlapping memcpy load/store spans the whole region or more");
11177 CurrOffset -= Overlap;
11187 if (CurrOffset != 0) {
11188 LLT SrcTy = MRI.getType(Src);
11192 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11194 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11198 if (CurrOffset != 0) {
11199 LLT DstTy = MRI.getType(Dst);
11200 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11202 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11203 CurrOffset += TySize;
11207 MI.eraseFromParent();
11215 auto &MF = *
MI.getParent()->getParent();
11219 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11220 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11223 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11224 const auto &DstMMO = **
MI.memoperands_begin();
11225 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11227 if (DstAlignCanChange) {
11230 Align NewAlign =
DL.getABITypeAlign(IRTy);
11235 if (!
TRI->hasStackRealignment(MF))
11236 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11237 NewAlign = std::min(NewAlign, *StackAlign);
11239 if (NewAlign > Alignment) {
11248 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11250 MachineIRBuilder MIB(
MI);
11254 unsigned CurrOffset = 0;
11255 unsigned Size = KnownLen;
11256 SmallVector<Register, 16> LoadVals;
11257 for (
auto CopyTy : MemOps) {
11258 TypeSize TySize = CopyTy.getSizeInBytes();
11262 if (TySize >
Size) {
11263 unsigned Overlap = TySize -
Size;
11264 assert(Overlap < CurrOffset &&
11265 "overlapping memmove load spans the whole region or more");
11266 CurrOffset -= Overlap;
11274 if (CurrOffset != 0) {
11275 LLT SrcTy = MRI.getType(Src);
11278 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11280 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11281 CurrOffset += TySize;
11287 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11288 LLT CopyTy = MemOps[
I];
11293 if (TySize >
Size) {
11294 unsigned Overlap = TySize -
Size;
11295 assert(Overlap < CurrOffset &&
11296 "overlapping memmove store spans the whole region or more");
11297 CurrOffset -= Overlap;
11304 if (CurrOffset != 0) {
11305 LLT DstTy = MRI.getType(Dst);
11308 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11310 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11311 CurrOffset += TySize;
11314 MI.eraseFromParent();
11321 const unsigned Opc =
MI.getOpcode();
11322 assert((
Opc == TargetOpcode::G_MEMCPY ||
11323 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11324 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11325 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11326 "Expected memcpy like instruction");
11328 if (KnownLen == 0) {
11329 MI.eraseFromParent();
11333 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11334 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11337 if (
Opc == TargetOpcode::G_MEMMOVE)
11338 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11340 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11341 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11351 bool DstAlignCanChange;
11352 std::vector<LLT> MemOps;
11354 DstAlignCanChange, MemOps))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static bool hasSwiftErrorArg(MachineFunction &MF)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static RTLIB::Libcall getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI)
static std::pair< int, int > getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy)
Try to break down OrigTy into NarrowTy sized pieces.
static bool hasSameNumEltsOnAllVectorOperands(GenericMachineInstr &MI, MachineRegisterInfo &MRI, std::initializer_list< unsigned > NonVecOpIndices)
Check that all vector operands have same number of elements.
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg, LLT VecTy)
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, Type *FromType)
static void getUnmergeResults(SmallVectorImpl< Register > &Regs, const MachineInstr &MI)
Append the result registers of G_UNMERGE_VALUES MI to Regs.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
#define RTLIBCASE(LibcallPrefix)
static Type * getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Tracks DebugLocs between checkpoints and verifies that they are transferred.
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmTowardZero
static const fltSemantics & IEEEdouble()
static constexpr roundingMode rmNearestTiesToEven
opStatus
IEEE-754R 7: Default exception handling.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
APInt bitcastToAPInt() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
void negate()
Negate this APInt in place.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, unsigned hiBit)
Wrap version of getBitsSet.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
LLT getLLTTy(const MachineRegisterInfo &MRI) const
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Register getValueReg() const
Get the stored value register.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Represents a insert subvector.
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
Represents a threeway compare.
A base class for all GenericMachineInstrs.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr ElementCount getElementCount() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
constexpr LLT changeVectorElementType(LLT NewEltTy) const
Returns a vector with the same number of elements but the new element type.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLT changeVectorElementCount(ElementCount EC) const
Return a vector with the same element type and the new element count.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
static LLT floatIEEE(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerThreewayCompare(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI)
LLVM_ABI LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI)
Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
LLVM_ABI LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty)
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSSUBE(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerSMULH_UMULH(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerLoad(GAnyLoad &MI)
LLVM_ABI LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerAbsToAddXor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPEXT_BF16(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizerHelper::LegalizeResult createAtomicLibcall(MachineInstr &MI) const
LLVM_ABI LegalizeResult lowerFConstant(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerBitreverse(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
Legalize a vector instruction by increasing the number of vector elements involved and ignoring the a...
LLVM_ABI LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTLS(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy)
Multi-way shift legalization: directly split wide shifts into target-sized parts in a single step,...
LLVM_ABI Register lowerRoundInexactToOdd(LLT ResultTy, Register Op)
LLVM_ABI LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, Register Dst, Register Src, uint64_t KnownLen, Align Alignment, bool DstAlignCanChange, ArrayRef< LLT > MemOps)
LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI Register buildConstantShiftPart(unsigned Opcode, unsigned PartIdx, unsigned NumParts, ArrayRef< Register > SrcParts, const ShiftParams &Params, LLT TargetTy, LLT ShiftAmtTy)
Generates a single output part for constant shifts using direct indexing.
LLVM_ABI void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by truncating the operand's ty...
LLVM_ABI LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI, unsigned NumElts)
LLVM_ABI LegalizeResult lowerFPTOUI(MachineInstr &MI)
const TargetLowering & getTargetLowering() const
LLVM_ABI LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
LLVM_ABI LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult bitcastInsertSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_INSERT_SUBVECTOR to CastTy.
LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B, const LibcallLoweringInfo *Libcalls=nullptr)
LLVM_ABI LegalizeResult lowerUnmergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by replacing the value type.
LLVM_ABI LegalizeResult scalarizeVectorBooleanStore(GStore &MI)
Given a store of a boolean vector, scalarize it.
LLVM_ABI LegalizeResult lowerBitcast(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerReadWriteRegister(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, LLT HalfTy, LLT ShiftAmtTy)
LLVM_ABI LegalizeResult lowerISFPCLASS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPExtAndTruncMem(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFAbs(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerVectorReduction(MachineInstr &MI)
const LegalizerInfo & getLegalizerInfo() const
Expose LegalizerInfo so the clients can re-use.
LLVM_ABI LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult fewerElementsVectorMultiEltType(GenericMachineInstr &MI, unsigned NumElts, std::initializer_list< unsigned > NonVecOpIndices={})
Handles most opcodes.
LLVM_ABI LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarShiftByConstantMultiway(MachineInstr &MI, const APInt &Amt, LLT TargetTy, LLT ShiftAmtTy)
Optimized path for constant shift amounts using static indexing.
LLVM_ABI void widenScalarSrcUsingFPExt(MachineInstr &MI, LLT WideTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val)
Create a store of Val to a stack temporary and return a load as the same type as Res.
LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMODF(MachineInstr &MI)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ AlreadyLegal
Instruction was already legal and no change was made to the MachineFunction.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult 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.