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();
1197 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1202 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1206 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1213 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1219 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1221 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1234 const auto [OeqLibcall, OeqPred] =
1236 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1238 const auto [UnoLibcall, UnoPred] =
1240 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1255 const auto [OeqLibcall, OeqPred] =
1260 const auto [UnoLibcall, UnoPred] =
1265 if (NotOeq && NotUno)
1284 const auto [InversedLibcall, InversedPred] =
1286 if (!BuildLibcall(InversedLibcall,
1311 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1313 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1316 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1322 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1327 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1329 switch (
MI.getOpcode()) {
1332 case TargetOpcode::G_MUL:
1333 case TargetOpcode::G_SDIV:
1334 case TargetOpcode::G_UDIV:
1335 case TargetOpcode::G_SREM:
1336 case TargetOpcode::G_UREM:
1337 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1338 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1346 case TargetOpcode::G_FADD:
1347 case TargetOpcode::G_FSUB:
1348 case TargetOpcode::G_FMUL:
1349 case TargetOpcode::G_FDIV:
1350 case TargetOpcode::G_FMA:
1351 case TargetOpcode::G_FPOW:
1352 case TargetOpcode::G_FREM:
1353 case TargetOpcode::G_FCOS:
1354 case TargetOpcode::G_FSIN:
1355 case TargetOpcode::G_FTAN:
1356 case TargetOpcode::G_FACOS:
1357 case TargetOpcode::G_FASIN:
1358 case TargetOpcode::G_FATAN:
1359 case TargetOpcode::G_FATAN2:
1360 case TargetOpcode::G_FCOSH:
1361 case TargetOpcode::G_FSINH:
1362 case TargetOpcode::G_FTANH:
1363 case TargetOpcode::G_FLOG10:
1364 case TargetOpcode::G_FLOG:
1365 case TargetOpcode::G_FLOG2:
1366 case TargetOpcode::G_FEXP:
1367 case TargetOpcode::G_FEXP2:
1368 case TargetOpcode::G_FEXP10:
1369 case TargetOpcode::G_FCEIL:
1370 case TargetOpcode::G_FFLOOR:
1371 case TargetOpcode::G_FMINNUM:
1372 case TargetOpcode::G_FMAXNUM:
1373 case TargetOpcode::G_FMINIMUMNUM:
1374 case TargetOpcode::G_FMAXIMUMNUM:
1375 case TargetOpcode::G_FSQRT:
1376 case TargetOpcode::G_FRINT:
1377 case TargetOpcode::G_FNEARBYINT:
1378 case TargetOpcode::G_INTRINSIC_TRUNC:
1379 case TargetOpcode::G_INTRINSIC_ROUND:
1380 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1381 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1385 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1393 case TargetOpcode::G_FSINCOS: {
1394 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1398 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1403 case TargetOpcode::G_FMODF: {
1404 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1408 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1413 case TargetOpcode::G_LROUND:
1414 case TargetOpcode::G_LLROUND:
1415 case TargetOpcode::G_INTRINSIC_LRINT:
1416 case TargetOpcode::G_INTRINSIC_LLRINT: {
1417 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1421 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1423 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1429 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1432 MI.eraseFromParent();
1435 case TargetOpcode::G_FPOWI:
1436 case TargetOpcode::G_FLDEXP: {
1437 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1441 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1443 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1448 {
MI.getOperand(1).getReg(), HLTy, 0},
1449 {
MI.getOperand(2).getReg(), ITy, 1}};
1450 Args[1].Flags[0].setSExt();
1452 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1457 case TargetOpcode::G_FPEXT:
1458 case TargetOpcode::G_FPTRUNC: {
1461 if (!FromTy || !ToTy)
1468 case TargetOpcode::G_FCMP: {
1472 MI.eraseFromParent();
1475 case TargetOpcode::G_FPTOSI:
1476 case TargetOpcode::G_FPTOUI: {
1480 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1481 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1484 FromTy, LocObserver);
1489 case TargetOpcode::G_SITOFP:
1490 case TargetOpcode::G_UITOFP: {
1491 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1494 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1496 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1503 case TargetOpcode::G_ATOMICRMW_XCHG:
1504 case TargetOpcode::G_ATOMICRMW_ADD:
1505 case TargetOpcode::G_ATOMICRMW_SUB:
1506 case TargetOpcode::G_ATOMICRMW_AND:
1507 case TargetOpcode::G_ATOMICRMW_OR:
1508 case TargetOpcode::G_ATOMICRMW_XOR:
1509 case TargetOpcode::G_ATOMIC_CMPXCHG:
1510 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1516 case TargetOpcode::G_BZERO:
1517 case TargetOpcode::G_MEMCPY:
1518 case TargetOpcode::G_MEMMOVE:
1519 case TargetOpcode::G_MEMSET: {
1524 MI.eraseFromParent();
1527 case TargetOpcode::G_GET_FPENV:
1528 case TargetOpcode::G_GET_FPMODE: {
1534 case TargetOpcode::G_SET_FPENV:
1535 case TargetOpcode::G_SET_FPMODE: {
1541 case TargetOpcode::G_RESET_FPENV:
1542 case TargetOpcode::G_RESET_FPMODE: {
1550 MI.eraseFromParent();
1557 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1560 switch (
MI.getOpcode()) {
1563 case TargetOpcode::G_IMPLICIT_DEF: {
1565 LLT DstTy = MRI.getType(DstReg);
1573 if (SizeOp0 % NarrowSize != 0) {
1578 MI.eraseFromParent();
1582 int NumParts = SizeOp0 / NarrowSize;
1585 for (
int i = 0; i < NumParts; ++i)
1589 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1591 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1592 MI.eraseFromParent();
1595 case TargetOpcode::G_CONSTANT: {
1596 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1597 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1598 unsigned TotalSize = Ty.getSizeInBits();
1600 int NumParts = TotalSize / NarrowSize;
1603 for (
int I = 0;
I != NumParts; ++
I) {
1604 unsigned Offset =
I * NarrowSize;
1611 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1613 if (LeftoverBits != 0) {
1617 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1621 insertParts(
MI.getOperand(0).getReg(),
1622 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1624 MI.eraseFromParent();
1627 case TargetOpcode::G_SEXT:
1628 case TargetOpcode::G_ZEXT:
1629 case TargetOpcode::G_ANYEXT:
1631 case TargetOpcode::G_TRUNC: {
1635 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1637 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1641 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1642 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1643 MI.eraseFromParent();
1646 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1647 case TargetOpcode::G_FREEZE: {
1651 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1656 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1658 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1660 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1664 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1665 MI.eraseFromParent();
1668 case TargetOpcode::G_ADD:
1669 case TargetOpcode::G_SUB:
1670 case TargetOpcode::G_SADDO:
1671 case TargetOpcode::G_SSUBO:
1672 case TargetOpcode::G_SADDE:
1673 case TargetOpcode::G_SSUBE:
1674 case TargetOpcode::G_UADDO:
1675 case TargetOpcode::G_USUBO:
1676 case TargetOpcode::G_UADDE:
1677 case TargetOpcode::G_USUBE:
1679 case TargetOpcode::G_MUL:
1680 case TargetOpcode::G_UMULH:
1682 case TargetOpcode::G_EXTRACT:
1684 case TargetOpcode::G_INSERT:
1686 case TargetOpcode::G_LOAD: {
1688 Register DstReg = LoadMI.getDstReg();
1689 LLT DstTy = MRI.getType(DstReg);
1693 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1694 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1695 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1697 LoadMI.eraseFromParent();
1703 case TargetOpcode::G_ZEXTLOAD:
1704 case TargetOpcode::G_SEXTLOAD:
1705 case TargetOpcode::G_FPEXTLOAD: {
1707 Register DstReg = LoadMI.getDstReg();
1708 Register PtrReg = LoadMI.getPointerReg();
1710 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1711 auto &MMO = LoadMI.getMMO();
1714 if (MemSize == NarrowSize) {
1716 }
else if (MemSize < NarrowSize) {
1717 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1718 }
else if (MemSize > NarrowSize) {
1730 LoadMI.eraseFromParent();
1733 case TargetOpcode::G_STORE: {
1736 Register SrcReg = StoreMI.getValueReg();
1737 LLT SrcTy = MRI.getType(SrcReg);
1738 if (SrcTy.isVector())
1741 int NumParts = SizeOp0 / NarrowSize;
1743 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1744 if (SrcTy.isVector() && LeftoverBits != 0)
1747 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1748 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1750 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1751 StoreMI.eraseFromParent();
1757 case TargetOpcode::G_FPTRUNCSTORE: {
1759 Register SrcReg = StoreMI.getValueReg();
1760 Register PtrReg = StoreMI.getPointerReg();
1762 auto &MMO = StoreMI.getMMO();
1764 if (MemSize > NarrowSize) {
1768 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1769 if (MemSize == NarrowSize) {
1771 }
else if (MemSize < NarrowSize) {
1772 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1776 StoreMI.eraseFromParent();
1779 case TargetOpcode::G_SELECT:
1781 case TargetOpcode::G_AND:
1782 case TargetOpcode::G_OR:
1783 case TargetOpcode::G_XOR: {
1795 case TargetOpcode::G_SHL:
1796 case TargetOpcode::G_LSHR:
1797 case TargetOpcode::G_ASHR:
1799 case TargetOpcode::G_CTLZ:
1800 case TargetOpcode::G_CTLZ_ZERO_POISON:
1801 case TargetOpcode::G_CTTZ:
1802 case TargetOpcode::G_CTTZ_ZERO_POISON:
1803 case TargetOpcode::G_CTLS:
1804 case TargetOpcode::G_CTPOP:
1806 switch (
MI.getOpcode()) {
1807 case TargetOpcode::G_CTLZ:
1808 case TargetOpcode::G_CTLZ_ZERO_POISON:
1810 case TargetOpcode::G_CTTZ:
1811 case TargetOpcode::G_CTTZ_ZERO_POISON:
1813 case TargetOpcode::G_CTPOP:
1815 case TargetOpcode::G_CTLS:
1825 case TargetOpcode::G_INTTOPTR:
1833 case TargetOpcode::G_PTRTOINT:
1841 case TargetOpcode::G_PHI: {
1844 if (SizeOp0 % NarrowSize != 0)
1847 unsigned NumParts = SizeOp0 / NarrowSize;
1851 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1859 for (
unsigned i = 0; i < NumParts; ++i) {
1860 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1862 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1863 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1864 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1867 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1869 MI.eraseFromParent();
1872 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1873 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1877 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1883 case TargetOpcode::G_ICMP: {
1885 LLT SrcTy = MRI.getType(LHS);
1891 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1897 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1898 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1904 LLT ResTy = MRI.getType(Dst);
1909 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1911 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1912 auto LHS = std::get<0>(LHSAndRHS);
1913 auto RHS = std::get<1>(LHSAndRHS);
1914 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1921 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1922 auto LHS = std::get<0>(LHSAndRHS);
1923 auto RHS = std::get<1>(LHSAndRHS);
1924 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1925 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1926 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1927 TargetOpcode::G_ZEXT);
1934 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1935 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1936 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1941 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1945 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1950 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1954 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1957 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1960 LHSPartRegs[
I], RHSPartRegs[
I]);
1961 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1967 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1976 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1980 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1981 RHSLeftoverRegs[
I]);
1983 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1984 RHSLeftoverRegs[
I]);
1987 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1988 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1994 MI.eraseFromParent();
1997 case TargetOpcode::G_FCMP:
2006 case TargetOpcode::G_SEXT_INREG: {
2010 int64_t SizeInBits =
MI.getOperand(2).getImm();
2019 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2020 MO1.
setReg(TruncMIB.getReg(0));
2023 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2035 if (SizeOp0 % NarrowSize != 0)
2037 int NumParts = SizeOp0 / NarrowSize;
2045 for (
int i = 0; i < NumParts; ++i) {
2046 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2061 for (
int i = 0; i < NumParts; ++i) {
2064 PartialExtensionReg = DstRegs.
back();
2066 assert(PartialExtensionReg &&
2067 "Expected to visit partial extension before full");
2068 if (FullExtensionReg) {
2073 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2075 FullExtensionReg = DstRegs.
back();
2080 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2083 PartialExtensionReg = DstRegs.
back();
2089 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2090 MI.eraseFromParent();
2093 case TargetOpcode::G_BSWAP:
2094 case TargetOpcode::G_BITREVERSE: {
2095 if (SizeOp0 % NarrowSize != 0)
2100 unsigned NumParts = SizeOp0 / NarrowSize;
2101 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2104 for (
unsigned i = 0; i < NumParts; ++i) {
2105 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2106 {SrcRegs[NumParts - 1 - i]});
2110 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2113 MI.eraseFromParent();
2116 case TargetOpcode::G_PTR_ADD:
2117 case TargetOpcode::G_PTRMASK: {
2125 case TargetOpcode::G_FPTOUI:
2126 case TargetOpcode::G_FPTOSI:
2127 case TargetOpcode::G_FPTOUI_SAT:
2128 case TargetOpcode::G_FPTOSI_SAT:
2130 case TargetOpcode::G_FPEXT:
2137 case TargetOpcode::G_FLDEXP:
2138 case TargetOpcode::G_STRICT_FLDEXP:
2140 case TargetOpcode::G_VSCALE: {
2142 LLT Ty = MRI.getType(Dst);
2146 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2147 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2148 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2151 MI.eraseFromParent();
2158 LLT Ty = MRI.getType(Val);
2159 if (Ty.isScalar() && !Ty.isFloat())
2166 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2168 if (Ty.isPointer()) {
2169 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2171 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2177 if (Ty.isPointerVector())
2178 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2179 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2183 unsigned OpIdx,
unsigned ExtOpcode) {
2185 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2186 MO.
setReg(ExtB.getReg(0));
2192 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2194 MO.
setReg(ExtB.getReg(0));
2200 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2201 MO.
setReg(ExtB.getReg(0));
2205 unsigned OpIdx,
unsigned TruncOpcode) {
2207 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2209 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2216 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2218 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2223 unsigned OpIdx,
unsigned ExtOpcode) {
2225 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2227 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2236 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2238 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2244 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2254 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2261LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2266 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2267 if (DstTy.isVector())
2272 const int SrcSize = SrcTy.getSizeInBits();
2274 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2276 unsigned NumOps =
MI.getNumOperands();
2277 unsigned NumSrc =
MI.getNumOperands() - 1;
2278 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2280 if (WideSize >= DstSize) {
2284 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2285 const unsigned Offset = (
I - 1) * PartSize;
2298 ResultReg = NextResult;
2301 if (WideSize > DstSize)
2303 else if (DstTy.isPointer())
2305 else if (DstTy != WideTy)
2308 MI.eraseFromParent();
2333 const int GCD = std::gcd(SrcSize, WideSize);
2343 if (GCD == SrcSize) {
2346 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2347 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2353 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2355 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2359 const int PartsPerGCD = WideSize / GCD;
2363 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2365 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2372 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2374 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2375 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2378 MI.eraseFromParent();
2383LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2388 int NumDst =
MI.getNumOperands() - 1;
2389 Register SrcReg =
MI.getOperand(NumDst).getReg();
2390 LLT SrcTy = MRI.getType(SrcReg);
2394 Register Dst0Reg =
MI.getOperand(0).getReg();
2395 LLT DstTy = MRI.getType(Dst0Reg);
2404 dbgs() <<
"Not casting non-integral address space integer\n");
2409 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2417 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2426 SrcTy = MRI.getType(SrcReg);
2430 for (
int I = 1;
I != NumDst; ++
I) {
2431 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2432 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2436 MI.eraseFromParent();
2447 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2451 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2454 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2472 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2477 if (PartsPerRemerge == 1) {
2480 for (
int I = 0;
I != NumUnmerge; ++
I) {
2481 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2483 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2484 int Idx =
I * PartsPerUnmerge + J;
2486 MIB.addDef(
MI.getOperand(Idx).getReg());
2489 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2493 MIB.addUse(Unmerge.getReg(
I));
2496 SmallVector<Register, 16> Parts;
2497 for (
int J = 0; J != NumUnmerge; ++J)
2498 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2501 for (
int I = 0;
I != NumDst; ++
I) {
2502 for (
int J = 0; J < PartsPerRemerge; ++J) {
2503 const int Idx =
I * PartsPerRemerge + J;
2507 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2508 RemergeParts.
clear();
2512 MI.eraseFromParent();
2517LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2519 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2520 unsigned Offset =
MI.getOperand(2).getImm();
2523 if (SrcTy.
isVector() || DstTy.isVector())
2535 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2539 if (DstTy.isPointer())
2546 MI.eraseFromParent();
2551 LLT ShiftTy = SrcTy;
2560 MI.eraseFromParent();
2591LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2593 if (TypeIdx != 0 || WideTy.
isVector())
2603LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2607 std::optional<Register> CarryIn;
2608 switch (
MI.getOpcode()) {
2611 case TargetOpcode::G_SADDO:
2612 Opcode = TargetOpcode::G_ADD;
2613 ExtOpcode = TargetOpcode::G_SEXT;
2615 case TargetOpcode::G_SSUBO:
2616 Opcode = TargetOpcode::G_SUB;
2617 ExtOpcode = TargetOpcode::G_SEXT;
2619 case TargetOpcode::G_UADDO:
2620 Opcode = TargetOpcode::G_ADD;
2621 ExtOpcode = TargetOpcode::G_ZEXT;
2623 case TargetOpcode::G_USUBO:
2624 Opcode = TargetOpcode::G_SUB;
2625 ExtOpcode = TargetOpcode::G_ZEXT;
2627 case TargetOpcode::G_SADDE:
2628 Opcode = TargetOpcode::G_UADDE;
2629 ExtOpcode = TargetOpcode::G_SEXT;
2630 CarryIn =
MI.getOperand(4).getReg();
2632 case TargetOpcode::G_SSUBE:
2633 Opcode = TargetOpcode::G_USUBE;
2634 ExtOpcode = TargetOpcode::G_SEXT;
2635 CarryIn =
MI.getOperand(4).getReg();
2637 case TargetOpcode::G_UADDE:
2638 Opcode = TargetOpcode::G_UADDE;
2639 ExtOpcode = TargetOpcode::G_ZEXT;
2640 CarryIn =
MI.getOperand(4).getReg();
2642 case TargetOpcode::G_USUBE:
2643 Opcode = TargetOpcode::G_USUBE;
2644 ExtOpcode = TargetOpcode::G_ZEXT;
2645 CarryIn =
MI.getOperand(4).getReg();
2661 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2662 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2666 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2668 .buildInstr(Opcode, {WideTy, CarryOutTy},
2669 {LHSExt, RHSExt, *CarryIn})
2672 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2674 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2675 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2676 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2681 MI.eraseFromParent();
2686LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2688 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2689 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2690 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2691 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2692 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2705 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2712 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2716 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2717 {ShiftL, ShiftR},
MI.getFlags());
2722 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2725 MI.eraseFromParent();
2730LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2739 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2741 LLT SrcTy = MRI.getType(
LHS);
2742 LLT OverflowTy = MRI.getType(OriginalOverflow);
2749 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2750 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2751 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2758 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2760 MachineInstrBuilder Mulo;
2761 if (WideMulCanOverflow)
2762 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2763 {LeftOperand, RightOperand});
2765 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2770 MachineInstrBuilder ExtResult;
2777 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2781 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2784 if (WideMulCanOverflow) {
2792 MI.eraseFromParent();
2798 unsigned Opcode =
MI.getOpcode();
2802 case TargetOpcode::G_ATOMICRMW_XCHG:
2803 case TargetOpcode::G_ATOMICRMW_ADD:
2804 case TargetOpcode::G_ATOMICRMW_SUB:
2805 case TargetOpcode::G_ATOMICRMW_AND:
2806 case TargetOpcode::G_ATOMICRMW_OR:
2807 case TargetOpcode::G_ATOMICRMW_XOR:
2808 case TargetOpcode::G_ATOMICRMW_MIN:
2809 case TargetOpcode::G_ATOMICRMW_MAX:
2810 case TargetOpcode::G_ATOMICRMW_UMIN:
2811 case TargetOpcode::G_ATOMICRMW_UMAX:
2812 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2818 case TargetOpcode::G_ATOMIC_CMPXCHG:
2819 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2826 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2836 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2841 case TargetOpcode::G_EXTRACT:
2842 return widenScalarExtract(
MI, TypeIdx, WideTy);
2843 case TargetOpcode::G_INSERT:
2844 return widenScalarInsert(
MI, TypeIdx, WideTy);
2845 case TargetOpcode::G_MERGE_VALUES:
2846 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2847 case TargetOpcode::G_UNMERGE_VALUES:
2848 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2849 case TargetOpcode::G_SADDO:
2850 case TargetOpcode::G_SSUBO:
2851 case TargetOpcode::G_UADDO:
2852 case TargetOpcode::G_USUBO:
2853 case TargetOpcode::G_SADDE:
2854 case TargetOpcode::G_SSUBE:
2855 case TargetOpcode::G_UADDE:
2856 case TargetOpcode::G_USUBE:
2857 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2858 case TargetOpcode::G_UMULO:
2859 case TargetOpcode::G_SMULO:
2860 return widenScalarMulo(
MI, TypeIdx, WideTy);
2861 case TargetOpcode::G_SADDSAT:
2862 case TargetOpcode::G_SSUBSAT:
2863 case TargetOpcode::G_SSHLSAT:
2864 case TargetOpcode::G_UADDSAT:
2865 case TargetOpcode::G_USUBSAT:
2866 case TargetOpcode::G_USHLSAT:
2867 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2868 case TargetOpcode::G_CTTZ:
2869 case TargetOpcode::G_CTTZ_ZERO_POISON:
2870 case TargetOpcode::G_CTLZ:
2871 case TargetOpcode::G_CTLZ_ZERO_POISON:
2872 case TargetOpcode::G_CTLS:
2873 case TargetOpcode::G_CTPOP: {
2886 case TargetOpcode::G_CTTZ:
2887 case TargetOpcode::G_CTTZ_ZERO_POISON:
2888 case TargetOpcode::G_CTLZ_ZERO_POISON:
2889 ExtOpc = TargetOpcode::G_ANYEXT;
2891 case TargetOpcode::G_CTLS:
2892 ExtOpc = TargetOpcode::G_SEXT;
2895 ExtOpc = TargetOpcode::G_ZEXT;
2898 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2899 LLT CurTy = MRI.getType(SrcReg);
2900 unsigned NewOpc = Opcode;
2901 if (NewOpc == TargetOpcode::G_CTTZ) {
2908 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2910 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2916 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2926 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2928 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2933 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2934 Opcode == TargetOpcode::G_CTLZ
2939 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2940 MI.eraseFromParent();
2943 case TargetOpcode::G_BSWAP: {
2947 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2948 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2949 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2952 MI.getOperand(0).setReg(DstExt);
2956 LLT Ty = MRI.getType(DstReg);
2958 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2959 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2965 case TargetOpcode::G_BITREVERSE: {
2969 LLT Ty = MRI.getType(DstReg);
2972 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2974 MI.getOperand(0).setReg(DstExt);
2977 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2978 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2983 case TargetOpcode::G_FREEZE:
2984 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2991 case TargetOpcode::G_ABS:
2998 case TargetOpcode::G_ADD:
2999 case TargetOpcode::G_AND:
3000 case TargetOpcode::G_MUL:
3001 case TargetOpcode::G_OR:
3002 case TargetOpcode::G_XOR:
3003 case TargetOpcode::G_SUB:
3004 case TargetOpcode::G_SHUFFLE_VECTOR:
3020 case TargetOpcode::G_SBFX:
3021 case TargetOpcode::G_UBFX:
3035 case TargetOpcode::G_SHL:
3055 case TargetOpcode::G_ROTR:
3056 case TargetOpcode::G_ROTL:
3065 case TargetOpcode::G_SDIV:
3066 case TargetOpcode::G_SREM:
3067 case TargetOpcode::G_SMIN:
3068 case TargetOpcode::G_SMAX:
3069 case TargetOpcode::G_ABDS:
3077 case TargetOpcode::G_SDIVREM:
3087 case TargetOpcode::G_ASHR:
3088 case TargetOpcode::G_LSHR:
3092 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3093 : TargetOpcode::G_ZEXT;
3106 case TargetOpcode::G_UDIV:
3107 case TargetOpcode::G_UREM:
3108 case TargetOpcode::G_ABDU:
3115 case TargetOpcode::G_UDIVREM:
3124 case TargetOpcode::G_UMIN:
3125 case TargetOpcode::G_UMAX: {
3126 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3128 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3132 ? TargetOpcode::G_SEXT
3133 : TargetOpcode::G_ZEXT;
3143 case TargetOpcode::G_SELECT:
3153 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3160 case TargetOpcode::G_FPEXT:
3168 case TargetOpcode::G_FPTOSI:
3169 case TargetOpcode::G_FPTOUI:
3170 case TargetOpcode::G_INTRINSIC_LRINT:
3171 case TargetOpcode::G_INTRINSIC_LLRINT:
3172 case TargetOpcode::G_IS_FPCLASS:
3182 case TargetOpcode::G_SITOFP:
3192 case TargetOpcode::G_UITOFP:
3202 case TargetOpcode::G_FPTOSI_SAT:
3203 case TargetOpcode::G_FPTOUI_SAT:
3208 LLT Ty = MRI.getType(OldDst);
3209 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3211 MI.getOperand(0).setReg(ExtReg);
3212 uint64_t ShortBits = Ty.getScalarSizeInBits();
3215 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3226 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3227 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3235 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3243 case TargetOpcode::G_LOAD:
3244 case TargetOpcode::G_SEXTLOAD:
3245 case TargetOpcode::G_ZEXTLOAD:
3246 case TargetOpcode::G_FPEXTLOAD:
3252 case TargetOpcode::G_STORE: {
3256 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3257 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3258 if (!Ty.isScalar()) {
3266 MI.setMemRefs(MF, {NewMMO});
3273 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3274 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3280 case TargetOpcode::G_FPTRUNCSTORE:
3287 case TargetOpcode::G_CONSTANT: {
3290 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3291 MRI.getType(
MI.getOperand(0).getReg()));
3292 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3293 ExtOpc == TargetOpcode::G_ANYEXT) &&
3296 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3300 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3306 case TargetOpcode::G_FCONSTANT: {
3312 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3314 MI.eraseFromParent();
3317 case TargetOpcode::G_IMPLICIT_DEF: {
3323 case TargetOpcode::G_BRCOND:
3329 case TargetOpcode::G_FCMP:
3340 case TargetOpcode::G_ICMP:
3345 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3349 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3350 unsigned ExtOpcode =
3354 ? TargetOpcode::G_SEXT
3355 : TargetOpcode::G_ZEXT;
3362 case TargetOpcode::G_PTR_ADD:
3363 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3369 case TargetOpcode::G_PHI: {
3370 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3373 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3385 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3388 LLT VecTy = MRI.getType(VecReg);
3392 TargetOpcode::G_ANYEXT);
3406 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3422 LLT VecTy = MRI.getType(VecReg);
3441 case TargetOpcode::G_FADD:
3442 case TargetOpcode::G_FMUL:
3443 case TargetOpcode::G_FSUB:
3444 case TargetOpcode::G_FMA:
3445 case TargetOpcode::G_FMAD:
3446 case TargetOpcode::G_FNEG:
3447 case TargetOpcode::G_FABS:
3448 case TargetOpcode::G_FCANONICALIZE:
3449 case TargetOpcode::G_FMINNUM:
3450 case TargetOpcode::G_FMAXNUM:
3451 case TargetOpcode::G_FMINNUM_IEEE:
3452 case TargetOpcode::G_FMAXNUM_IEEE:
3453 case TargetOpcode::G_FMINIMUM:
3454 case TargetOpcode::G_FMAXIMUM:
3455 case TargetOpcode::G_FMINIMUMNUM:
3456 case TargetOpcode::G_FMAXIMUMNUM:
3457 case TargetOpcode::G_FDIV:
3458 case TargetOpcode::G_FREM:
3459 case TargetOpcode::G_FCEIL:
3460 case TargetOpcode::G_FFLOOR:
3461 case TargetOpcode::G_FCOS:
3462 case TargetOpcode::G_FSIN:
3463 case TargetOpcode::G_FTAN:
3464 case TargetOpcode::G_FACOS:
3465 case TargetOpcode::G_FASIN:
3466 case TargetOpcode::G_FATAN:
3467 case TargetOpcode::G_FATAN2:
3468 case TargetOpcode::G_FCOSH:
3469 case TargetOpcode::G_FSINH:
3470 case TargetOpcode::G_FTANH:
3471 case TargetOpcode::G_FLOG10:
3472 case TargetOpcode::G_FLOG:
3473 case TargetOpcode::G_FLOG2:
3474 case TargetOpcode::G_FRINT:
3475 case TargetOpcode::G_FNEARBYINT:
3476 case TargetOpcode::G_FSQRT:
3477 case TargetOpcode::G_FEXP:
3478 case TargetOpcode::G_FEXP2:
3479 case TargetOpcode::G_FEXP10:
3480 case TargetOpcode::G_FPOW:
3481 case TargetOpcode::G_INTRINSIC_TRUNC:
3482 case TargetOpcode::G_INTRINSIC_ROUND:
3483 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3487 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3493 case TargetOpcode::G_FMODF: {
3503 case TargetOpcode::G_FPOWI:
3504 case TargetOpcode::G_FLDEXP:
3505 case TargetOpcode::G_STRICT_FLDEXP: {
3507 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3528 case TargetOpcode::G_FFREXP: {
3541 case TargetOpcode::G_LROUND:
3542 case TargetOpcode::G_LLROUND:
3553 case TargetOpcode::G_INTTOPTR:
3561 case TargetOpcode::G_PTRTOINT:
3569 case TargetOpcode::G_BUILD_VECTOR: {
3573 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3579 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3587 case TargetOpcode::G_SEXT_INREG:
3596 case TargetOpcode::G_PTRMASK: {
3604 case TargetOpcode::G_VECREDUCE_ADD: {
3613 case TargetOpcode::G_VECREDUCE_FADD:
3614 case TargetOpcode::G_VECREDUCE_FMUL:
3615 case TargetOpcode::G_VECREDUCE_FMIN:
3616 case TargetOpcode::G_VECREDUCE_FMAX:
3617 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3618 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3623 LLT VecTy = MRI.getType(VecReg);
3630 case TargetOpcode::G_VSCALE: {
3637 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3642 case TargetOpcode::G_SPLAT_VECTOR: {
3651 case TargetOpcode::G_INSERT_SUBVECTOR: {
3659 LLT SubVecTy = MRI.getType(SubVec);
3663 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3664 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3665 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3669 auto SplatZero =
MIRBuilder.buildSplatVector(
3674 MI.eraseFromParent();
3678 case TargetOpcode::G_BITCAST:
3690 if (MRI.getType(Dst) == MRI.getType(Src)) {
3691 Observer.changingAllUsesOfReg(MRI, Dst);
3692 MRI.replaceRegWith(Dst, Src);
3693 Observer.finishedChangingAllUsesOfReg();
3694 MI.eraseFromParent();
3703 auto Unmerge =
B.buildUnmerge(Ty, Src);
3704 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3713 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3727 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3736 MI.eraseFromParent();
3747 MI.eraseFromParent();
3754 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3755 if (SrcTy.isVector()) {
3759 if (DstTy.isVector()) {
3760 int NumDstElt = DstTy.getNumElements();
3761 int NumSrcElt = SrcTy.getNumElements();
3764 LLT DstCastTy = DstEltTy;
3765 LLT SrcPartTy = SrcEltTy;
3769 if (NumSrcElt < NumDstElt) {
3780 SrcPartTy = SrcEltTy;
3781 }
else if (NumSrcElt > NumDstElt) {
3793 DstCastTy = DstEltTy;
3798 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3802 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3803 MI.eraseFromParent();
3807 if (DstTy.isVector()) {
3810 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3811 MI.eraseFromParent();
3827 unsigned NewEltSize,
3828 unsigned OldEltSize) {
3829 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3830 LLT IdxTy =
B.getMRI()->getType(Idx);
3833 auto OffsetMask =
B.buildConstant(
3835 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3836 return B.buildShl(IdxTy, OffsetIdx,
3837 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3852 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3856 unsigned OldNumElts = SrcVecTy.getNumElements();
3863 if (NewNumElts > OldNumElts) {
3874 if (NewNumElts % OldNumElts != 0)
3878 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3882 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3885 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3887 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3888 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3889 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3890 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3891 NewOps[
I] = Elt.getReg(0);
3894 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3896 MI.eraseFromParent();
3900 if (NewNumElts < OldNumElts) {
3901 if (NewEltSize % OldEltSize != 0)
3923 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3924 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3927 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3931 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3932 ScaledIdx).getReg(0);
3940 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3942 MI.eraseFromParent();
3956 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3957 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3958 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3959 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3962 auto EltMask =
B.buildConstant(
3966 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3967 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3970 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3974 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3988 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3989 MI.getFirst4RegLLTs();
4001 if (NewNumElts < OldNumElts) {
4002 if (NewEltSize % OldEltSize != 0)
4011 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4012 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4015 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4019 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4020 ScaledIdx).getReg(0);
4030 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4031 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4035 MI.eraseFromParent();
4065 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4069 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4070 return UnableToLegalize;
4075 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4077 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4086 MI.eraseFromParent();
4104 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4105 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4115 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4116 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4118 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4119 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4121 MI.eraseFromParent();
4147 uint64_t Idx = ES->getIndexImm();
4151 LLT DstTy = MRI.getType(Dst);
4152 LLT SrcTy = MRI.getType(Src);
4158 if (DstTy == CastTy)
4166 if (CastEltSize < DstEltSize)
4169 auto AdjustAmt = CastEltSize / DstEltSize;
4170 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4171 SrcTyMinElts % AdjustAmt != 0)
4176 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4177 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4180 ES->eraseFromParent();
4211 uint64_t Idx = ES->getIndexImm();
4215 LLT DstTy = MRI.getType(Dst);
4216 LLT BigVecTy = MRI.getType(BigVec);
4217 LLT SubVecTy = MRI.getType(SubVec);
4219 if (DstTy == CastTy)
4234 if (CastEltSize < DstEltSize)
4237 auto AdjustAmt = CastEltSize / DstEltSize;
4238 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4239 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4245 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4246 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4248 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4251 ES->eraseFromParent();
4259 LLT DstTy = MRI.getType(DstReg);
4269 if (MemSizeInBits != MemStoreSizeInBits) {
4286 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4290 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4291 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4293 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4296 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4298 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4301 if (DstTy != LoadTy)
4309 if (
MIRBuilder.getDataLayout().isBigEndian())
4327 uint64_t LargeSplitSize, SmallSplitSize;
4332 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4339 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4342 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4353 if (Alignment.value() * 8 > MemSizeInBits &&
4358 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4375 LLT PtrTy = MRI.getType(PtrReg);
4388 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4391 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4392 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4393 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4395 SmallPtr, *SmallMMO);
4397 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4398 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4400 if (AnyExtTy == DstTy)
4401 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4403 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4407 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4427 LLT SrcTy = MRI.getType(SrcReg);
4435 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4441 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4443 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4447 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4451 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4466 uint64_t LargeSplitSize, SmallSplitSize;
4473 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4476 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4485 if (SrcTy.isPointer()) {
4490 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4493 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4494 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4497 LLT PtrTy = MRI.getType(PtrReg);
4499 LargeSplitSize / 8);
4500 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4506 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4507 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4516 LLT SrcTy = MRI.getType(SrcReg);
4522 assert(SrcTy.isVector() &&
"Expect a vector store type");
4529 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4533 auto Elt =
MIRBuilder.buildExtractVectorElement(
4534 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4535 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4536 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4542 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4543 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4547 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4558 switch (
MI.getOpcode()) {
4559 case TargetOpcode::G_LOAD: {
4577 case TargetOpcode::G_STORE: {
4593 case TargetOpcode::G_SELECT: {
4597 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4599 dbgs() <<
"bitcast action not implemented for vector select\n");
4610 case TargetOpcode::G_AND:
4611 case TargetOpcode::G_OR:
4612 case TargetOpcode::G_XOR: {
4620 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4622 case TargetOpcode::G_INSERT_VECTOR_ELT:
4624 case TargetOpcode::G_CONCAT_VECTORS:
4626 case TargetOpcode::G_SHUFFLE_VECTOR:
4628 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4630 case TargetOpcode::G_INSERT_SUBVECTOR:
4638void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4647 switch(
MI.getOpcode()) {
4650 case TargetOpcode::G_FCONSTANT:
4652 case TargetOpcode::G_BITCAST:
4654 case TargetOpcode::G_SREM:
4655 case TargetOpcode::G_UREM: {
4656 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4658 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4659 {MI.getOperand(1), MI.getOperand(2)});
4661 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4663 MI.eraseFromParent();
4666 case TargetOpcode::G_SADDO:
4667 case TargetOpcode::G_SSUBO:
4669 case TargetOpcode::G_SADDE:
4671 case TargetOpcode::G_SSUBE:
4673 case TargetOpcode::G_UMULH:
4674 case TargetOpcode::G_SMULH:
4676 case TargetOpcode::G_SMULO:
4677 case TargetOpcode::G_UMULO: {
4680 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4681 LLT Ty = MRI.getType(Res);
4683 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4684 ? TargetOpcode::G_SMULH
4685 : TargetOpcode::G_UMULH;
4689 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4690 MI.removeOperand(1);
4693 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4701 if (Opcode == TargetOpcode::G_SMULH) {
4702 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4703 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4710 case TargetOpcode::G_FNEG: {
4711 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4714 Register CastedSubByReg = SubByReg;
4716 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4717 !SubByRegTy.getScalarType().isInteger()) {
4718 auto BitcastDst = SubByRegTy.changeElementType(
4720 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4726 if (ResTy != TyInt) {
4728 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4731 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4733 MI.eraseFromParent();
4736 case TargetOpcode::G_FSUB:
4737 case TargetOpcode::G_STRICT_FSUB: {
4738 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4739 LLT Ty = MRI.getType(Res);
4744 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4745 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4749 MI.eraseFromParent();
4752 case TargetOpcode::G_FMAD:
4754 case TargetOpcode::G_FFLOOR:
4756 case TargetOpcode::G_LROUND:
4757 case TargetOpcode::G_LLROUND: {
4760 LLT SrcTy = MRI.getType(SrcReg);
4761 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4764 MI.eraseFromParent();
4767 case TargetOpcode::G_INTRINSIC_ROUND:
4769 case TargetOpcode::G_FRINT: {
4772 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4775 case TargetOpcode::G_INTRINSIC_LRINT:
4776 case TargetOpcode::G_INTRINSIC_LLRINT: {
4779 LLT SrcTy = MRI.getType(SrcReg);
4781 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4783 MI.eraseFromParent();
4786 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4787 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4788 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4789 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4790 **
MI.memoperands_begin());
4792 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4793 MI.eraseFromParent();
4796 case TargetOpcode::G_LOAD:
4797 case TargetOpcode::G_SEXTLOAD:
4798 case TargetOpcode::G_ZEXTLOAD:
4800 case TargetOpcode::G_STORE:
4802 case TargetOpcode::G_CTLZ_ZERO_POISON:
4803 case TargetOpcode::G_CTTZ_ZERO_POISON:
4804 case TargetOpcode::G_CTLZ:
4805 case TargetOpcode::G_CTTZ:
4806 case TargetOpcode::G_CTPOP:
4807 case TargetOpcode::G_CTLS:
4810 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4812 Register NewRes = MRI.cloneVirtualRegister(Res);
4819 MI.eraseFromParent();
4823 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4824 const LLT CondTy = MRI.getType(CarryOut);
4825 const LLT Ty = MRI.getType(Res);
4827 Register NewRes = MRI.cloneVirtualRegister(Res);
4830 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4836 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4837 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4844 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4849 MI.eraseFromParent();
4853 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4858 MI.eraseFromParent();
4862 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4863 const LLT CondTy = MRI.getType(BorrowOut);
4864 const LLT Ty = MRI.getType(Res);
4867 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4873 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4874 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4881 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4882 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4884 MI.eraseFromParent();
4924 case G_MERGE_VALUES:
4926 case G_UNMERGE_VALUES:
4928 case TargetOpcode::G_SEXT_INREG: {
4929 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4930 int64_t SizeInBits =
MI.getOperand(2).getImm();
4932 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4933 LLT DstTy = MRI.getType(DstReg);
4934 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4937 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4938 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4939 MI.eraseFromParent();
4942 case G_EXTRACT_VECTOR_ELT:
4943 case G_INSERT_VECTOR_ELT:
4945 case G_SHUFFLE_VECTOR:
4947 case G_VECTOR_COMPRESS:
4949 case G_DYN_STACKALLOC:
4951 case G_INSERT_SUBVECTOR: {
4952 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4953 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4958 Register Subvector =
MI.getOperand(2).getReg();
4959 auto InsertionPointImm =
MI.getOperand(3).getImm();
4962 LLT DstTy = MRI.getType(Subvector);
4966 bool InsertInLowHalf = InsertionPointImm == 0;
4967 auto Extract =
MIRBuilder.buildExtractSubvector(
4969 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
4971 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4972 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4974 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4975 {LowHalf, HighHalf});
4976 MI.eraseFromParent();
4982 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4983 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4989 if (i >= InsertionPointImm &&
4991 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
4999 MI.eraseFromParent();
5003 case G_EXTRACT_SUBVECTOR: {
5006 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5008 LLT SrcTy = MRI.getType(SrcReg);
5009 LLT DstTy = MRI.getType(DstReg);
5011 if (SrcTy.isScalable())
5022 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5023 ExtractionPointImm + i)
5027 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5028 MI.eraseFromParent();
5033 case G_STACKRESTORE:
5043 case G_READ_REGISTER:
5044 case G_WRITE_REGISTER:
5051 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5052 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5058 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5063 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5070 case G_TRUNC_SSAT_S:
5071 case G_TRUNC_USAT_U:
5072 case G_TRUNC_SSAT_U:
5078 bool IsSigned =
MI.getOpcode() == G_ABDS;
5079 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5080 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5081 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5104 case G_MEMCPY_INLINE:
5105 case G_MEMSET_INLINE:
5117 case G_ATOMICRMW_SUB: {
5118 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5119 const LLT ValTy = MRI.getType(Val);
5123 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5124 MI.eraseFromParent();
5152 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5156 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5162 Align StackTypeAlign =
5169 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5170 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5175 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5187 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5190 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5201 "Converting bits to bytes lost precision");
5207 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5208 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5210 if (IdxTy != MRI.getType(Index))
5211 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5216 LLT PtrTy = MRI.getType(VecPtr);
5217 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5225 std::initializer_list<unsigned> NonVecOpIndices) {
5226 if (
MI.getNumMemOperands() != 0)
5234 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5243 if (!Ty.isVector()) {
5249 if (Ty.getNumElements() != NumElts)
5264 assert(Ty.isVector() &&
"Expected vector type");
5266 int NumParts, NumLeftover;
5267 std::tie(NumParts, NumLeftover) =
5270 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5271 for (
int i = 0; i < NumParts; ++i) {
5276 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5285 for (
unsigned i = 0; i <
N; ++i) {
5287 Ops.push_back(
Op.getReg());
5288 else if (
Op.isImm())
5289 Ops.push_back(
Op.getImm());
5290 else if (
Op.isPredicate())
5312 std::initializer_list<unsigned> NonVecOpIndices) {
5314 "Non-compatible opcode or not specified non-vector operands");
5315 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5317 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5318 unsigned NumDefs =
MI.getNumDefs();
5326 for (
unsigned i = 0; i < NumDefs; ++i) {
5327 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5335 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5336 ++UseIdx, ++UseNo) {
5339 MI.getOperand(UseIdx));
5348 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5352 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5354 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5355 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5358 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5359 Uses.push_back(InputOpsPieces[InputNo][i]);
5362 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5363 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5368 for (
unsigned i = 0; i < NumDefs; ++i)
5369 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5371 for (
unsigned i = 0; i < NumDefs; ++i)
5372 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5375 MI.eraseFromParent();
5382 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5384 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5385 unsigned NumDefs =
MI.getNumDefs();
5389 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5394 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5395 UseIdx += 2, ++UseNo) {
5403 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5405 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5406 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5408 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5411 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5412 Phi.addUse(InputOpsPieces[j][i]);
5413 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5423 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5425 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5428 MI.eraseFromParent();
5436 const int NumDst =
MI.getNumOperands() - 1;
5437 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5438 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5439 LLT SrcTy = MRI.getType(SrcReg);
5441 if (TypeIdx != 1 || NarrowTy == DstTy)
5448 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5451 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5465 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5466 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5467 const int PartsPerUnmerge = NumDst / NumUnmerge;
5469 for (
int I = 0;
I != NumUnmerge; ++
I) {
5470 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5472 for (
int J = 0; J != PartsPerUnmerge; ++J)
5473 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5474 MIB.addUse(Unmerge.getReg(
I));
5477 MI.eraseFromParent();
5484 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5488 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5490 if (NarrowTy == SrcTy)
5498 assert(SrcTy.isVector() &&
"Expected vector types");
5500 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5514 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5515 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5516 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5522 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5523 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5524 ++i,
Offset += NumNarrowTyElts) {
5527 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5530 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5531 MI.eraseFromParent();
5535 assert(TypeIdx == 0 &&
"Bad type index");
5536 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5551 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5552 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5554 for (
unsigned i = 0; i < NumParts; ++i) {
5556 for (
unsigned j = 0; j < NumElts; ++j)
5557 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5559 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5562 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5563 MI.eraseFromParent();
5571 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5573 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5575 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5577 InsertVal =
MI.getOperand(2).getReg();
5579 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5580 LLT VecTy = MRI.getType(SrcVec);
5586 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5590 MI.eraseFromParent();
5599 SplitPieces[IdxVal] = InsertVal;
5600 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5602 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5606 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5609 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5610 TargetOpcode::G_ANYEXT);
5614 LLT IdxTy = MRI.getType(Idx);
5615 int64_t PartIdx = IdxVal / NewNumElts;
5617 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5620 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5623 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5624 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5625 VecParts[PartIdx] = InsertPart.getReg(0);
5629 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5631 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5635 MI.eraseFromParent();
5655 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5667 LLT ValTy = MRI.getType(ValReg);
5676 int NumLeftover = -1;
5682 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5684 NumParts = NarrowRegs.
size();
5685 NumLeftover = NarrowLeftoverRegs.
size();
5692 LLT PtrTy = MRI.getType(AddrReg);
5702 auto MMO = LdStMI.
getMMO();
5704 unsigned NumParts,
unsigned Offset) ->
unsigned {
5707 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5709 unsigned ByteOffset =
Offset / 8;
5712 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5719 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5720 ValRegs.push_back(Dst);
5721 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5723 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5732 unsigned HandledOffset =
5733 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5737 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5740 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5741 LeftoverTy, NarrowLeftoverRegs);
5755 switch (
MI.getOpcode()) {
5756 case G_IMPLICIT_DEF:
5772 case G_FCANONICALIZE:
5789 case G_INTRINSIC_LRINT:
5790 case G_INTRINSIC_LLRINT:
5791 case G_INTRINSIC_ROUND:
5792 case G_INTRINSIC_ROUNDEVEN:
5795 case G_INTRINSIC_TRUNC:
5823 case G_FMINNUM_IEEE:
5824 case G_FMAXNUM_IEEE:
5846 case G_CTLZ_ZERO_POISON:
5848 case G_CTTZ_ZERO_POISON:
5865 case G_ADDRSPACE_CAST:
5878 case G_STRICT_FLDEXP:
5880 case G_TRUNC_SSAT_S:
5881 case G_TRUNC_SSAT_U:
5882 case G_TRUNC_USAT_U:
5890 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5895 case G_UNMERGE_VALUES:
5897 case G_BUILD_VECTOR:
5898 assert(TypeIdx == 0 &&
"not a vector type index");
5900 case G_CONCAT_VECTORS:
5904 case G_EXTRACT_SUBVECTOR: {
5906 LLT DstTy = MRI.getType(DstReg);
5908 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5918 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5919 uint64_t RequiredSubvectorIndex =
5923 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5926 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5929 MI.eraseFromParent();
5932 case G_EXTRACT_VECTOR_ELT:
5933 case G_INSERT_VECTOR_ELT:
5942 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5943 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5945 case G_SHUFFLE_VECTOR:
5951 case G_INTRINSIC_FPTRUNC_ROUND:
5961 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5962 "Not a bitcast operation");
5967 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5969 unsigned NewElemCount =
5972 if (NewElemCount == 1) {
5975 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5982 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5991 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5992 MI.eraseFromParent();
5998 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6002 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6003 MI.getFirst3RegLLTs();
6006 if (DstTy != Src1Ty)
6008 if (DstTy != Src2Ty)
6023 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6039 unsigned InputUsed[2] = {-1U, -1U};
6040 unsigned FirstMaskIdx =
High * NewElts;
6041 bool UseBuildVector =
false;
6042 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6044 int Idx = Mask[FirstMaskIdx + MaskOffset];
6049 if (
Input >= std::size(Inputs)) {
6056 Idx -=
Input * NewElts;
6060 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6061 if (InputUsed[OpNo] ==
Input) {
6064 }
else if (InputUsed[OpNo] == -1U) {
6066 InputUsed[OpNo] =
Input;
6071 if (OpNo >= std::size(InputUsed)) {
6074 UseBuildVector =
true;
6079 Ops.push_back(Idx + OpNo * NewElts);
6082 if (UseBuildVector) {
6087 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6089 int Idx = Mask[FirstMaskIdx + MaskOffset];
6094 if (
Input >= std::size(Inputs)) {
6101 Idx -=
Input * NewElts;
6105 .buildExtractVectorElement(
6106 EltTy, Inputs[
Input],
6112 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6113 }
else if (InputUsed[0] == -1U) {
6115 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6116 }
else if (NewElts == 1) {
6117 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6119 Register Op0 = Inputs[InputUsed[0]];
6123 : Inputs[InputUsed[1]];
6125 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6132 MI.eraseFromParent();
6145 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6151 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6154 const unsigned NumParts =
6156 : SrcTy.getNumElements();
6160 if (DstTy != NarrowTy)
6166 unsigned NumPartsLeft = NumParts;
6167 while (NumPartsLeft > 1) {
6168 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6171 .buildInstr(ScalarOpc, {NarrowTy},
6172 {SplitSrcs[Idx], SplitSrcs[Idx + 1]},
6176 SplitSrcs = PartialResults;
6177 PartialResults.
clear();
6178 NumPartsLeft = SplitSrcs.
size();
6182 MI.eraseFromParent();
6187 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6189 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]},
6193 MI.eraseFromParent();
6197 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6199 .buildInstr(RdxMI.getOpcode(), {DstTy},
6209 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6212 Register Acc = PartialReductions[0];
6213 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6214 if (Part == NumParts - 1) {
6215 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, {Acc, PartialReductions[Part]},
6219 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]},
6224 MI.eraseFromParent();
6230 unsigned int TypeIdx,
6232 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6233 MI.getFirst3RegLLTs();
6234 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6238 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6239 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6240 "Unexpected vecreduce opcode");
6241 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6242 ? TargetOpcode::G_FADD
6243 : TargetOpcode::G_FMUL;
6246 unsigned NumParts = SrcTy.getNumElements();
6249 for (
unsigned i = 0; i < NumParts; i++)
6251 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]},
6256 MI.eraseFromParent();
6263 unsigned ScalarOpc) {
6271 while (SplitSrcs.
size() > 1) {
6273 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6283 SplitSrcs = std::move(PartialRdxs);
6287 MI.getOperand(1).setReg(SplitSrcs[0]);
6294 const LLT HalfTy,
const LLT AmtTy) {
6296 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6297 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6301 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6302 MI.eraseFromParent();
6308 unsigned VTBits = 2 * NVTBits;
6311 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6312 if (Amt.
ugt(VTBits)) {
6314 }
else if (Amt.
ugt(NVTBits)) {
6317 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6318 }
else if (Amt == NVTBits) {
6326 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6329 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6330 if (Amt.
ugt(VTBits)) {
6332 }
else if (Amt.
ugt(NVTBits)) {
6334 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6336 }
else if (Amt == NVTBits) {
6340 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6342 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6344 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6350 if (Amt.
ugt(VTBits)) {
6352 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6353 }
else if (Amt.
ugt(NVTBits)) {
6355 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6357 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6358 }
else if (Amt == NVTBits) {
6361 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6363 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6365 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6367 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6374 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6375 MI.eraseFromParent();
6391 LLT DstTy = MRI.getType(DstReg);
6396 LLT ShiftAmtTy = MRI.getType(Amt);
6398 if (DstEltSize % 2 != 0)
6414 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6425 const unsigned NewBitSize = DstEltSize / 2;
6437 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6439 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6440 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6443 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6444 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6446 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6451 switch (
MI.getOpcode()) {
6452 case TargetOpcode::G_SHL: {
6454 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6456 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6457 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6458 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6461 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6462 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6464 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6466 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6468 ResultRegs[0] =
Lo.getReg(0);
6469 ResultRegs[1] =
Hi.getReg(0);
6472 case TargetOpcode::G_LSHR:
6473 case TargetOpcode::G_ASHR: {
6475 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6477 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6478 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6479 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6483 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6486 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6487 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6489 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6493 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6495 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6497 ResultRegs[0] =
Lo.getReg(0);
6498 ResultRegs[1] =
Hi.getReg(0);
6505 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6506 MI.eraseFromParent();
6515 LLT TargetTy,
LLT ShiftAmtTy) {
6518 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6520 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6521 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6522 const bool NeedsInterWordShift = ShiftBits != 0;
6525 case TargetOpcode::G_SHL: {
6528 if (PartIdx < ShiftWords)
6531 unsigned SrcIdx = PartIdx - ShiftWords;
6532 if (!NeedsInterWordShift)
6533 return SrcParts[SrcIdx];
6538 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6542 return Hi.getReg(0);
6545 case TargetOpcode::G_LSHR: {
6546 unsigned SrcIdx = PartIdx + ShiftWords;
6547 if (SrcIdx >= NumParts)
6549 if (!NeedsInterWordShift)
6550 return SrcParts[SrcIdx];
6554 if (SrcIdx + 1 < NumParts) {
6555 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6559 return Lo.getReg(0);
6562 case TargetOpcode::G_ASHR: {
6564 unsigned SrcIdx = PartIdx + ShiftWords;
6565 if (SrcIdx >= NumParts)
6567 if (!NeedsInterWordShift)
6568 return SrcParts[SrcIdx];
6573 (SrcIdx == NumParts - 1)
6577 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6599 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6600 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6605 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6614 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6615 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6617 auto IsZeroBitShift =
6625 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6626 : TargetOpcode::G_SHL;
6629 auto TargetBitsConst =
6631 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6636 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6641 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6643 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6647 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6660 LLT DstTy = MRI.getType(DstReg);
6664 const unsigned NumParts = DstBits / TargetBits;
6666 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6676 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6677 MI.eraseFromParent();
6682 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6683 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6689 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6693 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6696 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6697 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6701 for (
unsigned I = 0;
I < NumParts; ++
I)
6703 Params, TargetTy, ShiftAmtTy);
6705 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6706 MI.eraseFromParent();
6715 LLT DstTy = MRI.getType(DstReg);
6716 LLT ShiftAmtTy = MRI.getType(AmtReg);
6720 const unsigned NumParts = DstBits / TargetBits;
6722 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6739 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6751 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6752 auto TargetBitsLog2Const =
6753 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6754 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6757 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6759 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6767 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6768 auto TargetBitsMinusOneConst =
6769 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6771 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6772 TargetBitsMinusOneConst)
6775 FillValue = ZeroReg;
6783 for (
unsigned I = 0;
I < NumParts; ++
I) {
6785 Register InBoundsResult = FillValue;
6795 for (
unsigned K = 0;
K < NumParts; ++
K) {
6796 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy,
K);
6798 WordShift, WordShiftKConst);
6810 switch (
MI.getOpcode()) {
6811 case TargetOpcode::G_SHL:
6812 MainSrcIdx = (int)
I - (
int)
K;
6813 CarrySrcIdx = MainSrcIdx - 1;
6815 case TargetOpcode::G_LSHR:
6816 case TargetOpcode::G_ASHR:
6817 MainSrcIdx = (int)
I + (
int)
K;
6818 CarrySrcIdx = MainSrcIdx + 1;
6826 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6827 Register MainOp = SrcParts[MainSrcIdx];
6831 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6832 CarryOp = SrcParts[CarrySrcIdx];
6833 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6834 CarrySrcIdx >= (
int)NumParts)
6835 CarryOp = FillValue;
6841 ResultForK = FillValue;
6847 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6854 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6858 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6859 MI.eraseFromParent();
6866 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6869 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6884 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6889 "getNeutralElementForVecReduce called with invalid opcode!");
6890 case TargetOpcode::G_VECREDUCE_ADD:
6891 case TargetOpcode::G_VECREDUCE_OR:
6892 case TargetOpcode::G_VECREDUCE_XOR:
6893 case TargetOpcode::G_VECREDUCE_UMAX:
6895 case TargetOpcode::G_VECREDUCE_MUL:
6897 case TargetOpcode::G_VECREDUCE_AND:
6898 case TargetOpcode::G_VECREDUCE_UMIN:
6901 case TargetOpcode::G_VECREDUCE_SMAX:
6904 case TargetOpcode::G_VECREDUCE_SMIN:
6907 case TargetOpcode::G_VECREDUCE_FADD:
6909 case TargetOpcode::G_VECREDUCE_FMUL:
6911 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6912 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6913 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6914 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6922 unsigned Opc =
MI.getOpcode();
6924 case TargetOpcode::G_IMPLICIT_DEF:
6925 case TargetOpcode::G_LOAD: {
6933 case TargetOpcode::G_STORE:
6940 case TargetOpcode::G_AND:
6941 case TargetOpcode::G_OR:
6942 case TargetOpcode::G_XOR:
6943 case TargetOpcode::G_ADD:
6944 case TargetOpcode::G_SUB:
6945 case TargetOpcode::G_MUL:
6946 case TargetOpcode::G_FADD:
6947 case TargetOpcode::G_FSUB:
6948 case TargetOpcode::G_FMUL:
6949 case TargetOpcode::G_FDIV:
6950 case TargetOpcode::G_FCOPYSIGN:
6951 case TargetOpcode::G_UADDSAT:
6952 case TargetOpcode::G_USUBSAT:
6953 case TargetOpcode::G_SADDSAT:
6954 case TargetOpcode::G_SSUBSAT:
6955 case TargetOpcode::G_SMIN:
6956 case TargetOpcode::G_SMAX:
6957 case TargetOpcode::G_UMIN:
6958 case TargetOpcode::G_UMAX:
6959 case TargetOpcode::G_FMINNUM:
6960 case TargetOpcode::G_FMAXNUM:
6961 case TargetOpcode::G_FMINNUM_IEEE:
6962 case TargetOpcode::G_FMAXNUM_IEEE:
6963 case TargetOpcode::G_FMINIMUM:
6964 case TargetOpcode::G_FMAXIMUM:
6965 case TargetOpcode::G_FMINIMUMNUM:
6966 case TargetOpcode::G_FMAXIMUMNUM:
6967 case TargetOpcode::G_STRICT_FADD:
6968 case TargetOpcode::G_STRICT_FSUB:
6969 case TargetOpcode::G_STRICT_FMUL: {
6977 case TargetOpcode::G_SHL:
6978 case TargetOpcode::G_ASHR:
6979 case TargetOpcode::G_LSHR: {
6985 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6991 case TargetOpcode::G_FMA:
6992 case TargetOpcode::G_STRICT_FMA:
6993 case TargetOpcode::G_FSHR:
6994 case TargetOpcode::G_FSHL: {
7003 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
7004 case TargetOpcode::G_EXTRACT:
7011 case TargetOpcode::G_INSERT:
7012 case TargetOpcode::G_INSERT_VECTOR_ELT:
7013 case TargetOpcode::G_FREEZE:
7014 case TargetOpcode::G_FNEG:
7015 case TargetOpcode::G_FABS:
7016 case TargetOpcode::G_FSQRT:
7017 case TargetOpcode::G_FCEIL:
7018 case TargetOpcode::G_FFLOOR:
7019 case TargetOpcode::G_FNEARBYINT:
7020 case TargetOpcode::G_FRINT:
7021 case TargetOpcode::G_INTRINSIC_ROUND:
7022 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7023 case TargetOpcode::G_INTRINSIC_TRUNC:
7024 case TargetOpcode::G_BITREVERSE:
7025 case TargetOpcode::G_BSWAP:
7026 case TargetOpcode::G_FCANONICALIZE:
7027 case TargetOpcode::G_SEXT_INREG:
7028 case TargetOpcode::G_ABS:
7029 case TargetOpcode::G_CTLZ:
7030 case TargetOpcode::G_CTPOP:
7038 case TargetOpcode::G_SELECT: {
7039 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7041 if (!CondTy.isScalar() ||
7047 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7049 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7054 if (CondTy.isVector())
7064 case TargetOpcode::G_UNMERGE_VALUES:
7066 case TargetOpcode::G_PHI:
7068 case TargetOpcode::G_SHUFFLE_VECTOR:
7070 case TargetOpcode::G_BUILD_VECTOR: {
7072 for (
auto Op :
MI.uses()) {
7080 MIRBuilder.buildDeleteTrailingVectorElements(
7081 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7082 MI.eraseFromParent();
7085 case TargetOpcode::G_SEXT:
7086 case TargetOpcode::G_ZEXT:
7087 case TargetOpcode::G_ANYEXT:
7088 case TargetOpcode::G_TRUNC:
7089 case TargetOpcode::G_FPTRUNC:
7090 case TargetOpcode::G_FPEXT:
7091 case TargetOpcode::G_FPTOSI:
7092 case TargetOpcode::G_FPTOUI:
7093 case TargetOpcode::G_FPTOSI_SAT:
7094 case TargetOpcode::G_FPTOUI_SAT:
7095 case TargetOpcode::G_SITOFP:
7096 case TargetOpcode::G_UITOFP:
7097 case TargetOpcode::G_TRUNC_SSAT_S:
7098 case TargetOpcode::G_TRUNC_SSAT_U:
7099 case TargetOpcode::G_TRUNC_USAT_U: {
7106 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7109 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7117 case TargetOpcode::G_ICMP:
7118 case TargetOpcode::G_FCMP: {
7126 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7131 case TargetOpcode::G_BITCAST: {
7135 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7136 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7152 case TargetOpcode::G_VECREDUCE_FADD:
7153 case TargetOpcode::G_VECREDUCE_FMUL:
7154 case TargetOpcode::G_VECREDUCE_ADD:
7155 case TargetOpcode::G_VECREDUCE_MUL:
7156 case TargetOpcode::G_VECREDUCE_AND:
7157 case TargetOpcode::G_VECREDUCE_OR:
7158 case TargetOpcode::G_VECREDUCE_XOR:
7159 case TargetOpcode::G_VECREDUCE_SMAX:
7160 case TargetOpcode::G_VECREDUCE_SMIN:
7161 case TargetOpcode::G_VECREDUCE_UMAX:
7162 case TargetOpcode::G_VECREDUCE_UMIN: {
7163 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7165 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7166 auto NeutralElement = getNeutralElementForVecReduce(
7172 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7173 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7174 NeutralElement, Idx);
7178 MO.
setReg(NewVec.getReg(0));
7190 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7192 unsigned MaskNumElts = Mask.size();
7193 unsigned SrcNumElts = SrcTy.getNumElements();
7196 if (MaskNumElts == SrcNumElts)
7199 if (MaskNumElts < SrcNumElts) {
7207 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7208 MI.getOperand(1).getReg(),
7209 MI.getOperand(2).getReg(), NewMask);
7210 MI.eraseFromParent();
7215 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7216 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7225 MOps1[0] =
MI.getOperand(1).getReg();
7226 MOps2[0] =
MI.getOperand(2).getReg();
7228 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7229 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7233 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7235 if (Idx >=
static_cast<int>(SrcNumElts))
7236 Idx += PaddedMaskNumElts - SrcNumElts;
7241 if (MaskNumElts != PaddedMaskNumElts) {
7243 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7246 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7248 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7253 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7256 MI.eraseFromParent();
7262 unsigned int TypeIdx,
LLT MoreTy) {
7263 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7265 unsigned NumElts = DstTy.getNumElements();
7268 if (DstTy.isVector() && Src1Ty.isVector() &&
7269 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7277 if (DstTy != Src1Ty || DstTy != Src2Ty)
7285 for (
unsigned I = 0;
I != NumElts; ++
I) {
7287 if (Idx <
static_cast<int>(NumElts))
7290 NewMask[
I] = Idx - NumElts + WidenNumElts;
7294 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7295 MI.getOperand(1).getReg(),
7296 MI.getOperand(2).getReg(), NewMask);
7297 MI.eraseFromParent();
7306 unsigned SrcParts = Src1Regs.
size();
7307 unsigned DstParts = DstRegs.
size();
7309 unsigned DstIdx = 0;
7311 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7312 DstRegs[DstIdx] = FactorSum;
7317 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7319 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7320 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7322 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7328 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7329 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7330 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7331 unsigned i = RevI - 1;
7333 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7343 if (DstIdx != DstParts - 1) {
7344 MachineInstrBuilder Uaddo =
7345 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7346 FactorSum = Uaddo.
getReg(0);
7347 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7348 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7349 MachineInstrBuilder Uaddo =
7350 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7351 FactorSum = Uaddo.
getReg(0);
7352 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7353 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7357 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7358 for (
unsigned i = 2; i < Factors.
size(); ++i)
7359 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7362 CarrySumPrevDstIdx = CarrySum;
7363 DstRegs[DstIdx] = FactorSum;
7375 LLT DstType = MRI.getType(DstReg);
7377 if (DstType.isVector())
7380 unsigned Opcode =
MI.getOpcode();
7381 unsigned OpO, OpE, OpF;
7383 case TargetOpcode::G_SADDO:
7384 case TargetOpcode::G_SADDE:
7385 case TargetOpcode::G_UADDO:
7386 case TargetOpcode::G_UADDE:
7387 case TargetOpcode::G_ADD:
7388 OpO = TargetOpcode::G_UADDO;
7389 OpE = TargetOpcode::G_UADDE;
7390 OpF = TargetOpcode::G_UADDE;
7391 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7392 OpF = TargetOpcode::G_SADDE;
7394 case TargetOpcode::G_SSUBO:
7395 case TargetOpcode::G_SSUBE:
7396 case TargetOpcode::G_USUBO:
7397 case TargetOpcode::G_USUBE:
7398 case TargetOpcode::G_SUB:
7399 OpO = TargetOpcode::G_USUBO;
7400 OpE = TargetOpcode::G_USUBE;
7401 OpF = TargetOpcode::G_USUBE;
7402 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7403 OpF = TargetOpcode::G_SSUBE;
7410 unsigned NumDefs =
MI.getNumExplicitDefs();
7411 Register Src1 =
MI.getOperand(NumDefs).getReg();
7412 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7415 CarryDst =
MI.getOperand(1).getReg();
7416 if (
MI.getNumOperands() == NumDefs + 3)
7417 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7419 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7420 LLT LeftoverTy, DummyTy;
7422 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7427 int NarrowParts = Src1Regs.
size();
7428 Src1Regs.
append(Src1Left);
7429 Src2Regs.
append(Src2Left);
7432 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7434 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7437 if (i == e - 1 && CarryDst)
7438 CarryOut = CarryDst;
7440 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7443 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7444 {Src1Regs[i], Src2Regs[i]});
7445 }
else if (i == e - 1) {
7446 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7447 {Src1Regs[i], Src2Regs[i], CarryIn});
7449 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7450 {Src1Regs[i], Src2Regs[i], CarryIn});
7456 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7457 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7458 ArrayRef(DstRegs).drop_front(NarrowParts));
7460 MI.eraseFromParent();
7466 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7468 LLT Ty = MRI.getType(DstReg);
7472 unsigned Size = Ty.getSizeInBits();
7474 if (
Size % NarrowSize != 0)
7477 unsigned NumParts =
Size / NarrowSize;
7478 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7479 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7485 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7489 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7490 MI.eraseFromParent();
7500 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7503 LLT SrcTy = MRI.getType(Src);
7514 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7527 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7530 if (SizeOp1 % NarrowSize != 0)
7532 int NumParts = SizeOp1 / NarrowSize;
7535 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7539 uint64_t OpStart =
MI.getOperand(2).getImm();
7540 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7541 for (
int i = 0; i < NumParts; ++i) {
7542 unsigned SrcStart = i * NarrowSize;
7544 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7547 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7555 int64_t ExtractOffset;
7557 if (OpStart < SrcStart) {
7559 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7561 ExtractOffset = OpStart - SrcStart;
7562 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7566 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7568 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7569 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7576 if (MRI.getType(DstReg).isVector())
7577 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7578 else if (DstRegs.
size() > 1)
7579 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7582 MI.eraseFromParent();
7594 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7596 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7599 SrcRegs.
append(LeftoverRegs);
7603 uint64_t OpStart =
MI.getOperand(3).getImm();
7604 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7605 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7606 unsigned DstStart =
I * NarrowSize;
7608 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7616 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7618 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7622 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7630 int64_t ExtractOffset, InsertOffset;
7632 if (OpStart < DstStart) {
7634 ExtractOffset = DstStart - OpStart;
7635 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7637 InsertOffset = OpStart - DstStart;
7640 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7644 if (ExtractOffset != 0 || SegSize != OpSize) {
7646 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7647 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7650 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7651 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7655 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7659 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7662 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7664 MI.eraseFromParent();
7672 LLT DstTy = MRI.getType(DstReg);
7674 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7680 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7681 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7685 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7686 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7689 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7690 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7691 {Src0Regs[I], Src1Regs[I]});
7695 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7698 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7699 DstLeftoverRegs.
push_back(Inst.getReg(0));
7702 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7703 LeftoverTy, DstLeftoverRegs);
7705 MI.eraseFromParent();
7715 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7717 LLT DstTy = MRI.getType(DstReg);
7722 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7723 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7724 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7726 MI.eraseFromParent();
7736 Register CondReg =
MI.getOperand(1).getReg();
7737 LLT CondTy = MRI.getType(CondReg);
7738 if (CondTy.isVector())
7742 LLT DstTy = MRI.getType(DstReg);
7748 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7749 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7753 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7754 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7757 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7759 CondReg, Src1Regs[
I], Src2Regs[
I]);
7763 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7765 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7769 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7770 LeftoverTy, DstLeftoverRegs);
7772 MI.eraseFromParent();
7782 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7785 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7786 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7789 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7791 auto C_0 =
B.buildConstant(NarrowTy, 0);
7793 UnmergeSrc.getReg(1), C_0);
7794 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7795 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7796 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7797 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7798 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7799 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7801 MI.eraseFromParent();
7814 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7817 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7818 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7821 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7823 auto C_0 =
B.buildConstant(NarrowTy, 0);
7825 UnmergeSrc.getReg(0), C_0);
7826 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7827 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7828 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7829 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7830 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7831 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7833 MI.eraseFromParent();
7846 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7849 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7854 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7858 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7859 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7867 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7868 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7871 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7872 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7874 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7876 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7878 MI.eraseFromParent();
7888 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7891 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7892 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7894 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7895 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7896 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7898 MI.eraseFromParent();
7913 LLT ExpTy = MRI.getType(ExpReg);
7918 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7919 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7920 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7921 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7923 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7925 MI.getOperand(2).setReg(Trunc.getReg(0));
7932 unsigned Opc =
MI.getOpcode();
7935 auto QAction = LI.getAction(Q).Action;
7941 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7944 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7948 case TargetOpcode::G_CTLZ: {
7949 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7950 unsigned Len = SrcTy.getScalarSizeInBits();
7952 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7954 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7955 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7958 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7959 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7960 MI.eraseFromParent();
7976 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7977 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7980 Op = MIBOp.getReg(0);
7985 MI.eraseFromParent();
7988 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7991 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7995 case TargetOpcode::G_CTTZ: {
7996 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7998 unsigned Len = SrcTy.getScalarSizeInBits();
7999 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
8002 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
8003 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
8006 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8007 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
8008 MI.eraseFromParent();
8015 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8016 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8018 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8019 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8020 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8021 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8024 MI.eraseFromParent();
8028 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8029 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8033 case TargetOpcode::G_CTPOP: {
8035 LLT Ty = MRI.getType(SrcReg);
8036 unsigned Size = Ty.getScalarSizeInBits();
8048 auto C_1 =
B.buildConstant(Ty, 1);
8049 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8051 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8052 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8053 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8057 auto C_2 =
B.buildConstant(Ty, 2);
8058 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8060 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8061 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8062 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8063 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8070 auto C_4 =
B.buildConstant(Ty, 4);
8071 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8072 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8074 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8075 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8077 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8080 if (
Size == 16 && !Ty.isVector()) {
8082 auto C_8 =
B.buildConstant(Ty, 8);
8083 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8084 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8085 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8086 MI.eraseFromParent();
8095 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8097 auto IsMulSupported = [
this](
const LLT Ty) {
8098 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8101 if (IsMulSupported(Ty)) {
8102 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8103 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8105 auto ResTmp = B8Count;
8106 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8107 auto ShiftC =
B.buildConstant(Ty, Shift);
8108 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8109 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8111 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8113 MI.eraseFromParent();
8116 case TargetOpcode::G_CTLS: {
8117 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8121 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8122 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8124 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8130 MI.eraseFromParent();
8151 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8152 LLT Ty = MRI.getType(Dst);
8153 LLT ShTy = MRI.getType(Z);
8160 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8161 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8166 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8167 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8171 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8184 MI.eraseFromParent();
8190 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8191 LLT Ty = MRI.getType(Dst);
8192 LLT ShTy = MRI.getType(Z);
8195 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8205 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8206 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8207 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8208 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8209 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8213 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8216 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8219 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8221 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8222 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8223 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8226 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8228 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8230 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8233 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8234 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8239 MI.eraseFromParent();
8250 LLT Ty = MRI.getType(Dst);
8251 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8253 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8254 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8257 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8258 return lowerFunnelShiftAsShifts(
MI);
8262 if (Result == UnableToLegalize)
8263 return lowerFunnelShiftAsShifts(
MI);
8268 auto [Dst, Src] =
MI.getFirst2Regs();
8269 LLT DstTy = MRI.getType(Dst);
8270 LLT SrcTy = MRI.getType(Src);
8274 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8282 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8286 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8290 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8295 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8296 {UnmergeSrc.getReg(0)});
8297 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8298 {UnmergeSrc.getReg(1)});
8301 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8303 MI.eraseFromParent();
8320 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8324 LLT DstTy = MRI.getType(DstReg);
8325 LLT SrcTy = MRI.getType(SrcReg);
8333 SrcTy.getElementCount().divideCoefficientBy(2));
8346 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8358 MI.eraseFromParent();
8367 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8368 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8369 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8370 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8371 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8372 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8373 MI.eraseFromParent();
8378 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8380 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8381 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8386 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8387 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8389 return lowerRotateWithReverseRotate(
MI);
8392 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8393 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8394 bool IsFShLegal =
false;
8395 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8396 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8400 MI.eraseFromParent();
8405 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8408 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8413 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8414 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8415 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8421 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8422 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8424 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8430 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8431 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8433 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8435 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8440 MI.eraseFromParent();
8448 auto [Dst, Src] =
MI.getFirst2Regs();
8453 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8466 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8468 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8473 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8475 MI.eraseFromParent();
8483 auto [Dst, Src] =
MI.getFirst2Regs();
8487 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8498 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8499 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8501 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8508 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8509 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8510 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8512 MI.eraseFromParent();
8523 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8524 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8530 MI.eraseFromParent();
8535 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8538 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8539 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8540 MIRBuilder.buildSelect(Dst, Src, True, False);
8541 MI.eraseFromParent();
8545 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8565 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8572 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8573 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8574 MIRBuilder.buildSelect(Dst, Src, True, False);
8575 MI.eraseFromParent();
8579 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8585 if (DstTy.getScalarSizeInBits() == 32) {
8592 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8593 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8595 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8602 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8603 MI.eraseFromParent();
8611 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8615 if (SrcTy !=
S64 && SrcTy !=
S32)
8617 if (DstTy !=
S32 && DstTy !=
S64)
8644 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8646 MI.eraseFromParent();
8651 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8656 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8663 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8665 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8666 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8668 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8669 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8671 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8673 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8674 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8675 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8678 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8679 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8680 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8682 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask,
K);
8685 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8690 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8691 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8697 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8699 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8700 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8702 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8707 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8708 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8710 MI.eraseFromParent();
8716 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8718 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8719 unsigned SatWidth = DstTy.getScalarSizeInBits();
8723 APInt MinInt, MaxInt;
8746 if (AreExactFloatBounds) {
8748 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8751 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8753 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8762 MI.eraseFromParent();
8767 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8772 MI.eraseFromParent();
8779 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8787 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8797 MI.eraseFromParent();
8803 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8807 MI.eraseFromParent();
8814 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8815 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8816 "Only G_FPEXT and G_FPTRUNC are expected");
8818 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8823 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8825 StoreOpc = TargetOpcode::G_STORE;
8826 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8829 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8830 LoadOpc = TargetOpcode::G_LOAD;
8839 StackTy, StackTyAlign);
8840 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8843 StackTy, StackTyAlign);
8844 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8846 MI.eraseFromParent();
8854 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8855 assert(SrcTy.getScalarType().isBFloat16() &&
8856 "expected a bf16 source for bf16 fpext lowering");
8867 if (DstTy.getScalarType().isFloat32())
8872 MI.eraseFromParent();
8877 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8878 if (SrcTy.getScalarType().isBFloat16() &&
8879 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8891 auto [Dst, Src] =
MI.getFirst2Regs();
8895 if (MRI.getType(Src).isVector())
8899 unsigned Flags =
MI.getFlags();
8902 MI.eraseFromParent();
8906 const unsigned ExpMask = 0x7ff;
8907 const unsigned ExpBiasf64 = 1023;
8908 const unsigned ExpBiasf16 = 15;
8910 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8920 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8927 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8929 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8931 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8935 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8937 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8939 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8940 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8948 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8949 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
8960 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
8971 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
8987 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
8997 MI.eraseFromParent();
9004 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9012 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9038 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9040 MI.eraseFromParent();
9049 LLT OperandTy = MRI.getType(
Op);
9059 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9061 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9062 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9063 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9064 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9065 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9073 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9076 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9078 AbsWide, AbsNarrowAsWide);
9082 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9083 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9085 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9086 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9092 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9098 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9099 MI.eraseFromParent();
9105 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9106 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9109 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9112 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9119 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9120 LLT Ty = MRI.getType(Dst);
9122 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9123 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9124 MI.eraseFromParent();
9129 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9130 LLT Ty = MRI.getType(Src);
9131 auto Flags =
MI.getFlags();
9139 FracToUse = FracPart.getReg(0);
9141 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9145 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9147 FracToUse =
Select.getReg(0);
9150 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9153 MI.eraseFromParent();
9159 case TargetOpcode::G_SMIN:
9161 case TargetOpcode::G_SMAX:
9163 case TargetOpcode::G_UMIN:
9165 case TargetOpcode::G_UMAX:
9173 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9178 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9179 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9181 MI.eraseFromParent();
9190 LLT DstTy = MRI.getType(Dst);
9191 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9201 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9202 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9204 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9207 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9208 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9209 if (TLI.preferSelectsOverBooleanArithmetic(
9212 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9213 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9215 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9216 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9222 unsigned BoolExtOp =
9224 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9225 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9229 MI.eraseFromParent();
9235 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9236 const int Src0Size = Src0Ty.getScalarSizeInBits();
9237 const int Src1Size = Src1Ty.getScalarSizeInBits();
9247 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9248 Src0Ty.getScalarType().isInteger()))
9249 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9251 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9252 Src1Ty.getScalarType().isInteger()))
9253 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9258 auto NotSignBitMask =
MIRBuilder.buildConstant(
9262 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9264 if (Src0Ty == Src1Ty) {
9265 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9266 }
else if (Src0Size > Src1Size) {
9267 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9268 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9269 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9270 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9272 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9273 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9274 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9275 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9281 unsigned Flags =
MI.getFlags();
9286 if (DstTy == DstIntTy)
9287 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9293 MI.eraseFromParent();
9304 switch (
MI.getOpcode()) {
9305 case TargetOpcode::G_FMINNUM:
9306 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9308 case TargetOpcode::G_FMINIMUMNUM:
9309 NewOp = TargetOpcode::G_FMINNUM;
9311 case TargetOpcode::G_FMAXNUM:
9312 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9314 case TargetOpcode::G_FMAXIMUMNUM:
9315 NewOp = TargetOpcode::G_FMAXNUM;
9321 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9322 LLT Ty = MRI.getType(Dst);
9331 if (!VT->isKnownNeverSNaN(Src0))
9332 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9334 if (!VT->isKnownNeverSNaN(Src1))
9335 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9340 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9341 MI.eraseFromParent();
9347 unsigned Opc =
MI.getOpcode();
9348 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9349 LLT Ty = MRI.getType(Dst);
9352 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9354 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9355 unsigned OpcNonIeee =
9356 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9357 bool MinMaxMustRespectOrderedZero =
false;
9361 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9363 MinMaxMustRespectOrderedZero =
true;
9364 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9369 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9374 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9377 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9381 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9383 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9393 const unsigned Flags =
MI.getFlags();
9399 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9401 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9403 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9405 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9407 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9412 MI.eraseFromParent();
9419 LLT Ty = MRI.getType(DstReg);
9420 unsigned Flags =
MI.getFlags();
9425 MI.eraseFromParent();
9431 auto [DstReg,
X] =
MI.getFirst2Regs();
9432 const unsigned Flags =
MI.getFlags();
9433 const LLT Ty = MRI.getType(DstReg);
9445 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9447 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9452 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9453 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9454 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9455 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9457 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9459 MI.eraseFromParent();
9464 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9465 unsigned Flags =
MI.getFlags();
9466 LLT Ty = MRI.getType(DstReg);
9473 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9474 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9477 SrcReg, Zero, Flags);
9479 SrcReg, Trunc, Flags);
9483 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9484 MI.eraseFromParent();
9490 const unsigned NumOps =
MI.getNumOperands();
9491 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9492 unsigned PartSize = Src0Ty.getSizeInBits();
9497 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9498 const unsigned Offset = (
I - 1) * PartSize;
9501 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9504 MRI.createGenericVirtualRegister(WideTy);
9507 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9508 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9509 ResultReg = NextResult;
9512 if (DstTy.isPointer()) {
9513 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9514 DstTy.getAddressSpace())) {
9520 }
else if (WideTy != DstTy) {
9524 MI.eraseFromParent();
9530 const unsigned NumDst =
MI.getNumOperands() - 1;
9531 Register SrcReg =
MI.getOperand(NumDst).getReg();
9532 Register Dst0Reg =
MI.getOperand(0).getReg();
9533 LLT DstTy = MRI.getType(Dst0Reg);
9542 LLT IntTy = MRI.getType(SrcReg);
9547 unsigned Offset = DstSize;
9548 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9550 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9554 MI.eraseFromParent();
9573 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9574 InsertVal =
MI.getOperand(2).getReg();
9576 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9578 LLT VecTy = MRI.getType(SrcVec);
9588 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9589 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9591 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9594 MI.eraseFromParent();
9599 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9610 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9617 int64_t
Offset = IdxVal * EltBytes;
9628 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9631 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9633 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9636 MI.eraseFromParent();
9642 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9643 MI.getFirst3RegLLTs();
9653 for (
int Idx : Mask) {
9655 if (!
Undef.isValid())
9661 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9663 int NumElts = Src0Ty.getNumElements();
9664 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9665 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9666 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9668 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9670 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9675 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9676 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9677 MI.eraseFromParent();
9683 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9684 MI.getFirst4RegLLTs();
9686 if (VecTy.isScalableVector())
9702 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9707 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9710 std::optional<APInt> PassthruSplatVal =
9713 if (PassthruSplatVal.has_value()) {
9715 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9716 }
else if (HasPassthru) {
9717 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9718 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9724 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9728 unsigned NumElmts = VecTy.getNumElements();
9729 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9731 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9734 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9737 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9742 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9744 if (HasPassthru &&
I == NumElmts - 1) {
9747 auto AllLanesSelected =
MIRBuilder.buildICmp(
9749 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9750 {OutPos, EndOfVector});
9754 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9756 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9761 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9763 MI.eraseFromParent();
9780 if (Alignment >
Align(1)) {
9781 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9792 const auto &MF = *
MI.getMF();
9798 Register AllocSize =
MI.getOperand(1).getReg();
9801 LLT PtrTy = MRI.getType(Dst);
9802 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9809 MI.eraseFromParent();
9815 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9820 MI.eraseFromParent();
9826 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9831 MI.eraseFromParent();
9837 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9838 unsigned Offset =
MI.getOperand(2).getImm();
9841 if (SrcTy.isVector()) {
9842 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9843 unsigned DstSize = DstTy.getSizeInBits();
9845 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9846 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9848 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9852 for (
unsigned Idx =
Offset / SrcEltSize;
9853 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9854 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9856 if (SubVectorElts.
size() == 1)
9857 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9859 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9861 MI.eraseFromParent();
9867 if ((SrcTy.isPointer() &&
9868 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9869 (DstTy.isPointer() &&
9870 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9871 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9875 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9876 (SrcTy.isScalar() || SrcTy.isPointer() ||
9877 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9878 LLT SrcIntTy = SrcTy;
9879 if (!SrcTy.isScalar()) {
9881 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9885 if (DstTy.isPointer())
9887 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9893 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9897 if (DstTy.isPointer())
9900 MI.eraseFromParent();
9908 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9909 uint64_t
Offset =
MI.getOperand(3).getImm();
9911 LLT DstTy = MRI.getType(Src);
9912 LLT InsertTy = MRI.getType(InsertSrc);
9915 bool IsNonIntegralInsert =
9925 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9926 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9933 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9935 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9939 for (; Idx <
Offset / EltSize; ++Idx) {
9940 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9945 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9946 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9948 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9952 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
9954 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
9961 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9964 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9965 MI.eraseFromParent();
9974 if (IsNonIntegralDst || IsNonIntegralInsert) {
9975 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9979 LLT IntDstTy = DstTy;
9983 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9988 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9994 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10000 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10001 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10002 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10005 MI.eraseFromParent();
10011 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10012 MI.getFirst4RegLLTs();
10013 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10016 LLT BoolTy = Dst1Ty;
10018 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10027 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10033 auto ResultLowerThanLHS =
10037 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10041 auto LHSLessThanRHS =
10043 auto ResultNegative =
10045 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10049 MI.eraseFromParent();
10055 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10056 const LLT Ty = MRI.getType(Res);
10059 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10060 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10061 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10065 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10066 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10069 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10072 MI.eraseFromParent();
10077 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10078 const LLT Ty = MRI.getType(Res);
10081 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10082 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10083 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10087 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10088 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10090 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10093 MI.eraseFromParent();
10099 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10100 LLT Ty = MRI.getType(Res);
10104 switch (
MI.getOpcode()) {
10107 case TargetOpcode::G_UADDSAT:
10110 BaseOp = TargetOpcode::G_ADD;
10112 case TargetOpcode::G_SADDSAT:
10115 BaseOp = TargetOpcode::G_ADD;
10117 case TargetOpcode::G_USUBSAT:
10120 BaseOp = TargetOpcode::G_SUB;
10122 case TargetOpcode::G_SSUBSAT:
10125 BaseOp = TargetOpcode::G_SUB;
10140 uint64_t NumBits = Ty.getScalarSizeInBits();
10147 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10151 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10159 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10164 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10165 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10168 MI.eraseFromParent();
10174 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10175 LLT Ty = MRI.getType(Res);
10179 unsigned OverflowOp;
10180 switch (
MI.getOpcode()) {
10183 case TargetOpcode::G_UADDSAT:
10186 OverflowOp = TargetOpcode::G_UADDO;
10188 case TargetOpcode::G_SADDSAT:
10191 OverflowOp = TargetOpcode::G_SADDO;
10193 case TargetOpcode::G_USUBSAT:
10196 OverflowOp = TargetOpcode::G_USUBO;
10198 case TargetOpcode::G_SSUBSAT:
10201 OverflowOp = TargetOpcode::G_SSUBO;
10206 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10207 Register Tmp = OverflowRes.getReg(0);
10208 Register Ov = OverflowRes.getReg(1);
10217 uint64_t NumBits = Ty.getScalarSizeInBits();
10218 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10219 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10222 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10230 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10232 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10234 MI.eraseFromParent();
10240 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10241 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10242 "Expected shlsat opcode!");
10243 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10244 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10245 LLT Ty = MRI.getType(Res);
10249 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10250 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10259 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10264 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10266 MI.eraseFromParent();
10272 unsigned Opc =
MI.getOpcode();
10273 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10274 unsigned DstSize = DstTy.getScalarSizeInBits();
10275 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10277 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10280 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10283 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10284 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10287 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10288 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10291 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10293 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10299 MI.eraseFromParent();
10304 auto [Dst, Src] =
MI.getFirst2Regs();
10305 const LLT Ty = MRI.getType(Src);
10306 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10307 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10310 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10311 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10312 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10313 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10316 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10319 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10320 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10322 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10323 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10324 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10326 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10327 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10328 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10330 Res.getInstr()->getOperand(0).setReg(Dst);
10332 MI.eraseFromParent();
10339 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10342 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10343 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10344 return B.buildOr(Dst,
LHS,
RHS);
10349 auto [Dst, Src] =
MI.getFirst2Regs();
10350 const LLT SrcTy = MRI.getType(Src);
10351 unsigned Size = SrcTy.getScalarSizeInBits();
10352 unsigned VSize = SrcTy.getSizeInBits();
10355 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10356 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10357 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10358 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10363 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10364 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10365 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10369 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10392 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10396 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10399 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10403 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10407 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10412 MI.eraseFromParent();
10420 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10421 int NameOpIdx = IsRead ? 1 : 0;
10422 int ValRegIndex = IsRead ? 0 : 1;
10424 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10425 const LLT Ty = MRI.getType(ValReg);
10427 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10434 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10435 Fn,
MI.getDebugLoc()));
10439 MI.eraseFromParent();
10448 MI.eraseFromParent();
10454 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10455 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10456 Register Result =
MI.getOperand(0).getReg();
10457 LLT OrigTy = MRI.getType(Result);
10461 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10462 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10464 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10466 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10467 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10470 MI.eraseFromParent();
10476 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10481 MI.eraseFromParent();
10486 MI.eraseFromParent();
10493 unsigned BitSize = SrcTy.getScalarSizeInBits();
10497 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10504 APInt ExpMask = Inf;
10506 APInt QNaNBitMask =
10510 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10511 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10512 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10513 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10514 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10516 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10520 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10522 LLT DstTyCopy = DstTy;
10524 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10552 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10555 Mask &= ~PartialCheck;
10564 else if (PartialCheck ==
fcZero)
10576 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10577 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10578 auto SubnormalRes =
10580 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10582 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10583 appendToRes(SubnormalRes);
10590 else if (PartialCheck ==
fcInf)
10595 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10602 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10603 if (PartialCheck ==
fcNan) {
10607 }
else if (PartialCheck ==
fcQNan) {
10617 Abs, InfWithQnanBitC);
10618 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10625 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10627 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10628 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10631 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10633 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10636 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10637 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10639 appendToRes(NormalRes);
10643 MI.eraseFromParent();
10649 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10650 MI.getFirst4RegLLTs();
10659 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10660 Op1Ty = MRI.getType(Op1Reg);
10661 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10662 Op2Ty = MRI.getType(Op2Reg);
10666 if (MaskTy.isScalar()) {
10674 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10677 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10679 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10681 if (DstTy.isVector()) {
10683 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10684 MaskReg = ShufSplat.getReg(0);
10688 }
else if (!DstTy.isVector()) {
10693 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10697 if (!Op1Ty.getScalarType().isAnyScalar() &&
10698 !Op1Ty.getScalarType().isInteger())
10699 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10701 if (!Op2Ty.getScalarType().isAnyScalar() &&
10702 !Op2Ty.getScalarType().isInteger()) {
10704 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10705 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10708 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10709 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10710 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10715 if (DstTy == Op1TyInt)
10718 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10722 MI.eraseFromParent();
10728 unsigned Opcode =
MI.getOpcode();
10731 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10732 : TargetOpcode::G_UDIV,
10733 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10735 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10736 : TargetOpcode::G_UREM,
10737 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10738 MI.eraseFromParent();
10748 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10752 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10755 MI.eraseFromParent();
10765 Register SrcReg =
MI.getOperand(1).getReg();
10766 LLT Ty = MRI.getType(SrcReg);
10767 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10770 MI.eraseFromParent();
10776 Register SrcReg =
MI.getOperand(1).getReg();
10777 Register DestReg =
MI.getOperand(0).getReg();
10779 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10780 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10783 MI.eraseFromParent();
10789 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10790 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10791 "Expected G_ABDS or G_ABDU instruction");
10793 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10794 LLT Ty = MRI.getType(LHS);
10804 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10806 MI.eraseFromParent();
10812 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10813 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10814 "Expected G_ABDS or G_ABDU instruction");
10816 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10817 LLT Ty = MRI.getType(LHS);
10822 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10823 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10824 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10826 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10827 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10829 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10831 MI.eraseFromParent();
10836 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10841 if (!(SrcTy.getScalarType().isAnyScalar() ||
10842 SrcTy.getScalarType().isInteger())) {
10844 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10845 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10848 if (MRI.getType(DstReg) != TyInt) {
10852 .buildAnd(TyInt, CastedSrc,
10855 DstTy.getScalarSizeInBits())))
10867 MI.eraseFromParent();
10873 Register SrcReg =
MI.getOperand(1).getReg();
10874 LLT SrcTy = MRI.getType(SrcReg);
10875 LLT DstTy = MRI.getType(SrcReg);
10878 if (SrcTy.isScalar()) {
10883 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10894 Register ListPtr =
MI.getOperand(1).getReg();
10895 LLT PtrTy = MRI.getType(ListPtr);
10902 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10904 const Align A(
MI.getOperand(2).getImm());
10906 if (
A > TLI.getMinStackArgumentAlignment()) {
10908 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10909 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10910 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10911 VAList = AndDst.getReg(0);
10918 LLT LLTTy = MRI.getType(Dst);
10921 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10922 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10927 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10929 Align EltAlignment =
DL.getABITypeAlign(Ty);
10932 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10934 MI.eraseFromParent();
10939 unsigned OpCode =
MI.getOpcode();
10940 assert((OpCode == TargetOpcode::G_SMULFIX ||
10941 OpCode == TargetOpcode::G_UMULFIX ||
10942 OpCode == TargetOpcode::G_SMULFIXSAT ||
10943 OpCode == TargetOpcode::G_UMULFIXSAT) &&
10944 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
10945 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10946 LLT Ty = MRI.getType(Dst);
10947 unsigned Scale =
MI.getOperand(3).getImm();
10949 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
10950 OpCode == TargetOpcode::G_UMULFIXSAT);
10951 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
10952 OpCode == TargetOpcode::G_SMULFIXSAT);
10954 if (!Saturating && Scale == 0) {
10956 MI.eraseFromParent();
10962 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
10985 MI.eraseFromParent();
10992 unsigned NumBits = Ty.getScalarSizeInBits();
10994 if (!Ty.isVector() && ValVRegAndVal) {
10995 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
11003 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11026 auto &MF = *
MI.getParent()->getParent();
11031 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11032 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11035 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11036 const auto &DstMMO = **
MI.memoperands_begin();
11038 if (DstAlignCanChange) {
11041 Align NewAlign =
DL.getABITypeAlign(IRTy);
11042 if (NewAlign > Alignment) {
11051 MachineIRBuilder MIB(
MI);
11053 LLT LargestTy = MemOps[0];
11054 for (
unsigned i = 1; i < MemOps.
size(); i++)
11056 LargestTy = MemOps[i];
11068 LLT PtrTy = MRI.getType(Dst);
11069 unsigned DstOff = 0;
11070 unsigned Size = KnownLen;
11071 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11072 LLT Ty = MemOps[
I];
11075 if (TySize >
Size) {
11079 DstOff -= TySize -
Size;
11089 TLI.isTruncateFree(LargestVT, VT))
11090 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11103 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11106 MIB.buildStore(
Value, Ptr, *StoreMMO);
11111 MI.eraseFromParent();
11119 auto &MF = *
MI.getParent()->getParent();
11123 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11124 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11127 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11133 const auto &DstMMO = **
MI.memoperands_begin();
11134 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11136 if (DstAlignCanChange) {
11139 Align NewAlign =
DL.getABITypeAlign(IRTy);
11144 if (!
TRI->hasStackRealignment(MF))
11145 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11146 NewAlign = std::min(NewAlign, *StackAlign);
11148 if (NewAlign > Alignment) {
11157 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11159 MachineIRBuilder MIB(
MI);
11165 unsigned CurrOffset = 0;
11166 unsigned Size = KnownLen;
11167 for (
auto CopyTy : MemOps) {
11168 TypeSize TySize = CopyTy.getSizeInBytes();
11172 if (TySize >
Size) {
11173 unsigned Overlap = TySize -
Size;
11174 assert(Overlap < CurrOffset &&
11175 "overlapping memcpy load/store spans the whole region or more");
11176 CurrOffset -= Overlap;
11186 if (CurrOffset != 0) {
11187 LLT SrcTy = MRI.getType(Src);
11191 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11193 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11197 if (CurrOffset != 0) {
11198 LLT DstTy = MRI.getType(Dst);
11199 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11201 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11202 CurrOffset += TySize;
11206 MI.eraseFromParent();
11214 auto &MF = *
MI.getParent()->getParent();
11218 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11219 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11222 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11223 const auto &DstMMO = **
MI.memoperands_begin();
11224 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11226 if (DstAlignCanChange) {
11229 Align NewAlign =
DL.getABITypeAlign(IRTy);
11234 if (!
TRI->hasStackRealignment(MF))
11235 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11236 NewAlign = std::min(NewAlign, *StackAlign);
11238 if (NewAlign > Alignment) {
11247 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11249 MachineIRBuilder MIB(
MI);
11253 unsigned CurrOffset = 0;
11254 unsigned Size = KnownLen;
11255 SmallVector<Register, 16> LoadVals;
11256 for (
auto CopyTy : MemOps) {
11257 TypeSize TySize = CopyTy.getSizeInBytes();
11261 if (TySize >
Size) {
11262 unsigned Overlap = TySize -
Size;
11263 assert(Overlap < CurrOffset &&
11264 "overlapping memmove load spans the whole region or more");
11265 CurrOffset -= Overlap;
11273 if (CurrOffset != 0) {
11274 LLT SrcTy = MRI.getType(Src);
11277 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11279 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11280 CurrOffset += TySize;
11286 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11287 LLT CopyTy = MemOps[
I];
11292 if (TySize >
Size) {
11293 unsigned Overlap = TySize -
Size;
11294 assert(Overlap < CurrOffset &&
11295 "overlapping memmove store spans the whole region or more");
11296 CurrOffset -= Overlap;
11303 if (CurrOffset != 0) {
11304 LLT DstTy = MRI.getType(Dst);
11307 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11309 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11310 CurrOffset += TySize;
11313 MI.eraseFromParent();
11320 const unsigned Opc =
MI.getOpcode();
11321 assert((
Opc == TargetOpcode::G_MEMCPY ||
11322 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11323 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11324 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11325 "Expected memcpy like instruction");
11327 if (KnownLen == 0) {
11328 MI.eraseFromParent();
11332 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11333 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11336 if (
Opc == TargetOpcode::G_MEMMOVE)
11337 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11339 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11340 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11350 bool DstAlignCanChange;
11351 std::vector<LLT> MemOps;
11353 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.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Type * getType() const
All values are typed, get the type of this value.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
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 MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
LLVM_ABI bool canLowerMemCpyFamily(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned MaxLen, Register &Dst, Register &Src, uint64_t &KnownLen, Align &Alignment, bool &DstAlignCanChange, std::vector< LLT > &MemOps)
Matcher for memcpy-like instructions.
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
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.