44#define DEBUG_TYPE "legalizer"
57static std::pair<int, int>
63 unsigned NumParts =
Size / NarrowSize;
64 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
67 if (LeftoverSize == 0)
72 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
130 auto Step = LI.getAction(
MI, MRI);
131 switch (Step.Action) {
146 return bitcast(
MI, Step.TypeIdx, Step.NewType);
149 return lower(
MI, Step.TypeIdx, Step.NewType);
158 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
166void LegalizerHelper::insertParts(
Register DstReg,
188 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
190 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
191 return mergeMixedSubvectors(DstReg, AllRegs);
197 extractGCDType(GCDRegs, GCDTy, PartReg);
198 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
199 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
204 LLT Ty = MRI.getType(
Reg);
212void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
215 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
216 appendVectorElts(AllElts, PartRegs[i]);
219 if (!MRI.getType(Leftover).isVector())
222 appendVectorElts(AllElts, Leftover);
224 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
230 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
232 const int StartIdx = Regs.
size();
233 const int NumResults =
MI.getNumOperands() - 1;
235 for (
int I = 0;
I != NumResults; ++
I)
236 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
241 LLT SrcTy = MRI.getType(SrcReg);
242 if (SrcTy == GCDTy) {
248 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
255 LLT SrcTy = MRI.getType(SrcReg);
257 extractGCDType(Parts, GCDTy, SrcReg);
261LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
263 unsigned PadStrategy) {
268 int NumOrigSrc = VRegs.
size();
274 if (NumOrigSrc < NumParts * NumSubParts) {
275 if (PadStrategy == TargetOpcode::G_ZEXT)
276 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
277 else if (PadStrategy == TargetOpcode::G_ANYEXT)
278 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
280 assert(PadStrategy == TargetOpcode::G_SEXT);
285 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
301 for (
int I = 0;
I != NumParts; ++
I) {
302 bool AllMergePartsArePadding =
true;
305 for (
int J = 0; J != NumSubParts; ++J) {
306 int Idx =
I * NumSubParts + J;
307 if (Idx >= NumOrigSrc) {
308 SubMerge[J] = PadReg;
312 SubMerge[J] = VRegs[Idx];
315 AllMergePartsArePadding =
false;
321 if (AllMergePartsArePadding && !AllPadReg) {
322 if (PadStrategy == TargetOpcode::G_ANYEXT)
323 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
324 else if (PadStrategy == TargetOpcode::G_ZEXT)
325 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
334 Remerge[
I] = AllPadReg;
338 if (NumSubParts == 1)
339 Remerge[
I] = SubMerge[0];
341 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
344 if (AllMergePartsArePadding && !AllPadReg)
345 AllPadReg = Remerge[
I];
348 VRegs = std::move(Remerge);
352void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
354 LLT DstTy = MRI.getType(DstReg);
359 if (DstTy == LCMTy) {
360 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
364 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
373 UnmergeDefs[0] = DstReg;
374 for (
unsigned I = 1;
I != NumDefs; ++
I)
375 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
378 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
386#define RTLIBCASE_INT(LibcallPrefix) \
390 return RTLIB::LibcallPrefix##32; \
392 return RTLIB::LibcallPrefix##64; \
394 return RTLIB::LibcallPrefix##128; \
396 llvm_unreachable("unexpected size"); \
400#define RTLIBCASE(LibcallPrefix) \
404 return RTLIB::LibcallPrefix##32; \
406 return RTLIB::LibcallPrefix##64; \
408 return RTLIB::LibcallPrefix##80; \
410 return RTLIB::LibcallPrefix##128; \
412 llvm_unreachable("unexpected size"); \
417 case TargetOpcode::G_LROUND:
419 case TargetOpcode::G_LLROUND:
421 case TargetOpcode::G_MUL:
423 case TargetOpcode::G_SDIV:
425 case TargetOpcode::G_UDIV:
427 case TargetOpcode::G_SREM:
429 case TargetOpcode::G_UREM:
431 case TargetOpcode::G_CTLZ_ZERO_POISON:
433 case TargetOpcode::G_FADD:
435 case TargetOpcode::G_FSUB:
437 case TargetOpcode::G_FMUL:
439 case TargetOpcode::G_FDIV:
441 case TargetOpcode::G_FEXP:
443 case TargetOpcode::G_FEXP2:
445 case TargetOpcode::G_FEXP10:
447 case TargetOpcode::G_FREM:
449 case TargetOpcode::G_FPOW:
451 case TargetOpcode::G_FPOWI:
453 case TargetOpcode::G_FMA:
455 case TargetOpcode::G_FSIN:
457 case TargetOpcode::G_FCOS:
459 case TargetOpcode::G_FTAN:
461 case TargetOpcode::G_FASIN:
463 case TargetOpcode::G_FACOS:
465 case TargetOpcode::G_FATAN:
467 case TargetOpcode::G_FATAN2:
469 case TargetOpcode::G_FSINH:
471 case TargetOpcode::G_FCOSH:
473 case TargetOpcode::G_FTANH:
475 case TargetOpcode::G_FSINCOS:
477 case TargetOpcode::G_FMODF:
479 case TargetOpcode::G_FLOG10:
481 case TargetOpcode::G_FLOG:
483 case TargetOpcode::G_FLOG2:
485 case TargetOpcode::G_FLDEXP:
487 case TargetOpcode::G_FCEIL:
489 case TargetOpcode::G_FFLOOR:
491 case TargetOpcode::G_FMINNUM:
493 case TargetOpcode::G_FMAXNUM:
495 case TargetOpcode::G_FMINIMUMNUM:
497 case TargetOpcode::G_FMAXIMUMNUM:
499 case TargetOpcode::G_FSQRT:
501 case TargetOpcode::G_FRINT:
503 case TargetOpcode::G_FNEARBYINT:
505 case TargetOpcode::G_INTRINSIC_TRUNC:
507 case TargetOpcode::G_INTRINSIC_ROUND:
509 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
511 case TargetOpcode::G_INTRINSIC_LRINT:
513 case TargetOpcode::G_INTRINSIC_LLRINT:
525 Attribute::SwiftError);
540 AttributeList CallerAttrs =
F.getAttributes();
541 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
542 .removeAttribute(Attribute::NoAlias)
543 .removeAttribute(Attribute::NonNull)
548 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
549 CallerAttrs.hasRetAttr(Attribute::SExt))
560 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
567 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
575 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
578 if (Ret->getNumImplicitOperands() != 1)
581 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
598 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
603 Info.OrigRet = Result;
606 (Result.Ty->isVoidTy() ||
607 Result.Ty ==
MIRBuilder.getMF().getFunction().getReturnType()) &&
618 if (
MI && Info.LoweredTailCall) {
619 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
629 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
630 "Expected instr following MI to be return or debug inst?");
633 Next->eraseFromParent();
634 }
while (
MI->getNextNode());
649 RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(
Libcall);
650 if (LibcallImpl == RTLIB::Unsupported)
654 const CallingConv::ID CC = Libcalls->getLibcallImplCallingConv(LibcallImpl);
668 Args.push_back({MO.getReg(), OpType, 0});
687 unsigned AddrSpace =
DL.getAllocaAddrSpace();
705 if (LibcallResult != LegalizeResult::Legalized)
713 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
714 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
715 MI.eraseFromParent();
730 LLT DstTy = MRI.getType(DstFrac);
735 unsigned AddrSpace =
DL.getAllocaAddrSpace();
736 MachinePointerInfo PtrInfo;
745 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
748 if (LibcallResult != LegalizeResult::Legalized)
754 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
755 MI.eraseFromParent();
766 case TargetOpcode::G_FPEXT:
768 case TargetOpcode::G_FPTRUNC:
770 case TargetOpcode::G_FPTOSI:
772 case TargetOpcode::G_FPTOUI:
774 case TargetOpcode::G_SITOFP:
776 case TargetOpcode::G_UITOFP:
786 if (FromType->isIntegerTy()) {
787 if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
788 Arg.
Flags[0].setSExt();
790 Arg.
Flags[0].setZExt();
801 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
805 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
809 LLT OpLLT = MRI.getType(Reg);
815 Args.push_back({Reg,
OpTy, 0});
818 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
819 RTLIB::Libcall RTLibcall;
820 unsigned Opc =
MI.getOpcode();
822 case TargetOpcode::G_BZERO:
823 RTLibcall = RTLIB::BZERO;
825 case TargetOpcode::G_MEMCPY:
826 RTLibcall = RTLIB::MEMCPY;
827 Args[0].Flags[0].setReturned();
829 case TargetOpcode::G_MEMMOVE:
830 RTLibcall = RTLIB::MEMMOVE;
831 Args[0].Flags[0].setReturned();
833 case TargetOpcode::G_MEMSET:
834 RTLibcall = RTLIB::MEMSET;
835 Args[0].Flags[0].setReturned();
844 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
847 if (RTLibcallImpl == RTLIB::Unsupported) {
854 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
861 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
871 if (Info.LoweredTailCall) {
872 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
882 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
883 "Expected instr following MI to be return or debug inst?");
886 Next->eraseFromParent();
887 }
while (
MI.getNextNode());
897 unsigned Opc =
MI.getOpcode();
899 auto &MMO = AtomicMI.getMMO();
900 auto Ordering = MMO.getMergedOrdering();
901 LLT MemType = MMO.getMemoryType();
904 return RTLIB::UNKNOWN_LIBCALL;
906#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
908 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
910 case TargetOpcode::G_ATOMIC_CMPXCHG:
911 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
912 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
913 return getOutlineAtomicHelper(LC, Ordering, MemSize);
915 case TargetOpcode::G_ATOMICRMW_XCHG: {
916 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
917 return getOutlineAtomicHelper(LC, Ordering, MemSize);
919 case TargetOpcode::G_ATOMICRMW_ADD:
920 case TargetOpcode::G_ATOMICRMW_SUB: {
921 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
922 return getOutlineAtomicHelper(LC, Ordering, MemSize);
924 case TargetOpcode::G_ATOMICRMW_AND: {
925 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
926 return getOutlineAtomicHelper(LC, Ordering, MemSize);
928 case TargetOpcode::G_ATOMICRMW_OR: {
929 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
930 return getOutlineAtomicHelper(LC, Ordering, MemSize);
932 case TargetOpcode::G_ATOMICRMW_XOR: {
933 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
934 return getOutlineAtomicHelper(LC, Ordering, MemSize);
937 return RTLIB::UNKNOWN_LIBCALL;
950 unsigned Opc =
MI.getOpcode();
952 case TargetOpcode::G_ATOMIC_CMPXCHG:
953 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
956 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
957 MI.getFirst4RegLLTs();
960 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
961 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
962 NewLLT) =
MI.getFirst5RegLLTs();
972 case TargetOpcode::G_ATOMICRMW_XCHG:
973 case TargetOpcode::G_ATOMICRMW_ADD:
974 case TargetOpcode::G_ATOMICRMW_SUB:
975 case TargetOpcode::G_ATOMICRMW_AND:
976 case TargetOpcode::G_ATOMICRMW_OR:
977 case TargetOpcode::G_ATOMICRMW_XOR: {
978 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
981 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
985 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
1000 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
1002 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
1005 if (RTLibcallImpl == RTLIB::Unsupported) {
1012 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
1026static RTLIB::Libcall
1028 RTLIB::Libcall RTLibcall;
1029 switch (
MI.getOpcode()) {
1030 case TargetOpcode::G_GET_FPENV:
1031 RTLibcall = RTLIB::FEGETENV;
1033 case TargetOpcode::G_SET_FPENV:
1034 case TargetOpcode::G_RESET_FPENV:
1035 RTLibcall = RTLIB::FESETENV;
1037 case TargetOpcode::G_GET_FPMODE:
1038 RTLibcall = RTLIB::FEGETMODE;
1040 case TargetOpcode::G_SET_FPMODE:
1041 case TargetOpcode::G_RESET_FPMODE:
1042 RTLibcall = RTLIB::FESETMODE;
1074 LLT StateTy = MRI.getType(Dst);
1077 MachinePointerInfo TempPtrInfo;
1081 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1086 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
1094 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1112 LLT StateTy = MRI.getType(Src);
1115 MachinePointerInfo TempPtrInfo;
1124 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1129 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1130 LocObserver,
nullptr);
1136static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1138#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1142 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1144 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1146 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1148 llvm_unreachable("unexpected size"); \
1181 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1184 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1191 LLT DstTy = MRI.getType(DstReg);
1192 const auto Cond =
Cmp->getCond();
1197 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1202 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1206 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1213 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1219 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1221 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1234 const auto [OeqLibcall, OeqPred] =
1236 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1238 const auto [UnoLibcall, UnoPred] =
1240 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1255 const auto [OeqLibcall, OeqPred] =
1260 const auto [UnoLibcall, UnoPred] =
1265 if (NotOeq && NotUno)
1284 const auto [InversedLibcall, InversedPred] =
1286 if (!BuildLibcall(InversedLibcall,
1311 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1313 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1316 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1322 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1327 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1329 switch (
MI.getOpcode()) {
1332 case TargetOpcode::G_MUL:
1333 case TargetOpcode::G_SDIV:
1334 case TargetOpcode::G_UDIV:
1335 case TargetOpcode::G_SREM:
1336 case TargetOpcode::G_UREM:
1337 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1338 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1346 case TargetOpcode::G_FADD:
1347 case TargetOpcode::G_FSUB:
1348 case TargetOpcode::G_FMUL:
1349 case TargetOpcode::G_FDIV:
1350 case TargetOpcode::G_FMA:
1351 case TargetOpcode::G_FPOW:
1352 case TargetOpcode::G_FREM:
1353 case TargetOpcode::G_FCOS:
1354 case TargetOpcode::G_FSIN:
1355 case TargetOpcode::G_FTAN:
1356 case TargetOpcode::G_FACOS:
1357 case TargetOpcode::G_FASIN:
1358 case TargetOpcode::G_FATAN:
1359 case TargetOpcode::G_FATAN2:
1360 case TargetOpcode::G_FCOSH:
1361 case TargetOpcode::G_FSINH:
1362 case TargetOpcode::G_FTANH:
1363 case TargetOpcode::G_FLOG10:
1364 case TargetOpcode::G_FLOG:
1365 case TargetOpcode::G_FLOG2:
1366 case TargetOpcode::G_FEXP:
1367 case TargetOpcode::G_FEXP2:
1368 case TargetOpcode::G_FEXP10:
1369 case TargetOpcode::G_FCEIL:
1370 case TargetOpcode::G_FFLOOR:
1371 case TargetOpcode::G_FMINNUM:
1372 case TargetOpcode::G_FMAXNUM:
1373 case TargetOpcode::G_FMINIMUMNUM:
1374 case TargetOpcode::G_FMAXIMUMNUM:
1375 case TargetOpcode::G_FSQRT:
1376 case TargetOpcode::G_FRINT:
1377 case TargetOpcode::G_FNEARBYINT:
1378 case TargetOpcode::G_INTRINSIC_TRUNC:
1379 case TargetOpcode::G_INTRINSIC_ROUND:
1380 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1381 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1385 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1393 case TargetOpcode::G_FSINCOS: {
1394 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1398 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1403 case TargetOpcode::G_FMODF: {
1404 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1408 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1413 case TargetOpcode::G_LROUND:
1414 case TargetOpcode::G_LLROUND:
1415 case TargetOpcode::G_INTRINSIC_LRINT:
1416 case TargetOpcode::G_INTRINSIC_LLRINT: {
1417 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1421 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1423 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1429 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1432 MI.eraseFromParent();
1435 case TargetOpcode::G_FPOWI:
1436 case TargetOpcode::G_FLDEXP: {
1437 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1441 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1443 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1448 {
MI.getOperand(1).getReg(), HLTy, 0},
1449 {
MI.getOperand(2).getReg(), ITy, 1}};
1450 Args[1].Flags[0].setSExt();
1452 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1457 case TargetOpcode::G_FPEXT:
1458 case TargetOpcode::G_FPTRUNC: {
1461 if (!FromTy || !ToTy)
1468 case TargetOpcode::G_FCMP: {
1472 MI.eraseFromParent();
1475 case TargetOpcode::G_FPTOSI:
1476 case TargetOpcode::G_FPTOUI: {
1480 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1481 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1484 FromTy, LocObserver);
1489 case TargetOpcode::G_SITOFP:
1490 case TargetOpcode::G_UITOFP: {
1491 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1494 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1496 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1503 case TargetOpcode::G_ATOMICRMW_XCHG:
1504 case TargetOpcode::G_ATOMICRMW_ADD:
1505 case TargetOpcode::G_ATOMICRMW_SUB:
1506 case TargetOpcode::G_ATOMICRMW_AND:
1507 case TargetOpcode::G_ATOMICRMW_OR:
1508 case TargetOpcode::G_ATOMICRMW_XOR:
1509 case TargetOpcode::G_ATOMIC_CMPXCHG:
1510 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1516 case TargetOpcode::G_BZERO:
1517 case TargetOpcode::G_MEMCPY:
1518 case TargetOpcode::G_MEMMOVE:
1519 case TargetOpcode::G_MEMSET: {
1524 MI.eraseFromParent();
1527 case TargetOpcode::G_GET_FPENV:
1528 case TargetOpcode::G_GET_FPMODE: {
1534 case TargetOpcode::G_SET_FPENV:
1535 case TargetOpcode::G_SET_FPMODE: {
1541 case TargetOpcode::G_RESET_FPENV:
1542 case TargetOpcode::G_RESET_FPMODE: {
1550 MI.eraseFromParent();
1557 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1560 switch (
MI.getOpcode()) {
1563 case TargetOpcode::G_IMPLICIT_DEF: {
1565 LLT DstTy = MRI.getType(DstReg);
1573 if (SizeOp0 % NarrowSize != 0) {
1578 MI.eraseFromParent();
1582 int NumParts = SizeOp0 / NarrowSize;
1585 for (
int i = 0; i < NumParts; ++i)
1589 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1591 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1592 MI.eraseFromParent();
1595 case TargetOpcode::G_CONSTANT: {
1596 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1597 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1598 unsigned TotalSize = Ty.getSizeInBits();
1600 int NumParts = TotalSize / NarrowSize;
1603 for (
int I = 0;
I != NumParts; ++
I) {
1604 unsigned Offset =
I * NarrowSize;
1611 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1613 if (LeftoverBits != 0) {
1617 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1621 insertParts(
MI.getOperand(0).getReg(),
1622 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1624 MI.eraseFromParent();
1627 case TargetOpcode::G_SEXT:
1628 case TargetOpcode::G_ZEXT:
1629 case TargetOpcode::G_ANYEXT:
1631 case TargetOpcode::G_TRUNC: {
1635 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1637 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1641 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1642 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1643 MI.eraseFromParent();
1646 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1647 case TargetOpcode::G_FREEZE: {
1651 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1656 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1658 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1660 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1664 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1665 MI.eraseFromParent();
1668 case TargetOpcode::G_ADD:
1669 case TargetOpcode::G_SUB:
1670 case TargetOpcode::G_SADDO:
1671 case TargetOpcode::G_SSUBO:
1672 case TargetOpcode::G_SADDE:
1673 case TargetOpcode::G_SSUBE:
1674 case TargetOpcode::G_UADDO:
1675 case TargetOpcode::G_USUBO:
1676 case TargetOpcode::G_UADDE:
1677 case TargetOpcode::G_USUBE:
1679 case TargetOpcode::G_MUL:
1680 case TargetOpcode::G_UMULH:
1682 case TargetOpcode::G_EXTRACT:
1684 case TargetOpcode::G_INSERT:
1686 case TargetOpcode::G_LOAD: {
1688 Register DstReg = LoadMI.getDstReg();
1689 LLT DstTy = MRI.getType(DstReg);
1693 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1694 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1695 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1697 LoadMI.eraseFromParent();
1703 case TargetOpcode::G_ZEXTLOAD:
1704 case TargetOpcode::G_SEXTLOAD:
1705 case TargetOpcode::G_FPEXTLOAD: {
1707 Register DstReg = LoadMI.getDstReg();
1708 Register PtrReg = LoadMI.getPointerReg();
1710 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1711 auto &MMO = LoadMI.getMMO();
1714 if (MemSize == NarrowSize) {
1716 }
else if (MemSize < NarrowSize) {
1717 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1718 }
else if (MemSize > NarrowSize) {
1730 LoadMI.eraseFromParent();
1733 case TargetOpcode::G_STORE: {
1736 Register SrcReg = StoreMI.getValueReg();
1737 LLT SrcTy = MRI.getType(SrcReg);
1738 if (SrcTy.isVector())
1741 int NumParts = SizeOp0 / NarrowSize;
1743 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1744 if (SrcTy.isVector() && LeftoverBits != 0)
1747 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1748 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1750 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1751 StoreMI.eraseFromParent();
1757 case TargetOpcode::G_FPTRUNCSTORE: {
1759 Register SrcReg = StoreMI.getValueReg();
1760 Register PtrReg = StoreMI.getPointerReg();
1762 auto &MMO = StoreMI.getMMO();
1764 if (MemSize > NarrowSize) {
1768 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1769 if (MemSize == NarrowSize) {
1771 }
else if (MemSize < NarrowSize) {
1772 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1776 StoreMI.eraseFromParent();
1779 case TargetOpcode::G_SELECT:
1781 case TargetOpcode::G_AND:
1782 case TargetOpcode::G_OR:
1783 case TargetOpcode::G_XOR: {
1795 case TargetOpcode::G_SHL:
1796 case TargetOpcode::G_LSHR:
1797 case TargetOpcode::G_ASHR:
1799 case TargetOpcode::G_CTLZ:
1800 case TargetOpcode::G_CTLZ_ZERO_POISON:
1801 case TargetOpcode::G_CTTZ:
1802 case TargetOpcode::G_CTTZ_ZERO_POISON:
1803 case TargetOpcode::G_CTLS:
1804 case TargetOpcode::G_CTPOP:
1806 switch (
MI.getOpcode()) {
1807 case TargetOpcode::G_CTLZ:
1808 case TargetOpcode::G_CTLZ_ZERO_POISON:
1810 case TargetOpcode::G_CTTZ:
1811 case TargetOpcode::G_CTTZ_ZERO_POISON:
1813 case TargetOpcode::G_CTPOP:
1815 case TargetOpcode::G_CTLS:
1825 case TargetOpcode::G_INTTOPTR:
1833 case TargetOpcode::G_PTRTOINT:
1841 case TargetOpcode::G_PHI: {
1844 if (SizeOp0 % NarrowSize != 0)
1847 unsigned NumParts = SizeOp0 / NarrowSize;
1851 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1859 for (
unsigned i = 0; i < NumParts; ++i) {
1860 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1862 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1863 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1864 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1867 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1869 MI.eraseFromParent();
1872 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1873 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1877 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1883 case TargetOpcode::G_ICMP: {
1885 LLT SrcTy = MRI.getType(LHS);
1891 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1897 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1898 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1904 LLT ResTy = MRI.getType(Dst);
1909 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1911 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1912 auto LHS = std::get<0>(LHSAndRHS);
1913 auto RHS = std::get<1>(LHSAndRHS);
1914 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1921 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1922 auto LHS = std::get<0>(LHSAndRHS);
1923 auto RHS = std::get<1>(LHSAndRHS);
1924 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1925 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1926 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1927 TargetOpcode::G_ZEXT);
1934 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1935 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1936 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1941 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1945 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1950 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1954 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1957 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1960 LHSPartRegs[
I], RHSPartRegs[
I]);
1961 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1967 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1976 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1980 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1981 RHSLeftoverRegs[
I]);
1983 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1984 RHSLeftoverRegs[
I]);
1987 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1988 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1994 MI.eraseFromParent();
1997 case TargetOpcode::G_FCMP:
2006 case TargetOpcode::G_SEXT_INREG: {
2010 int64_t SizeInBits =
MI.getOperand(2).getImm();
2019 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2020 MO1.
setReg(TruncMIB.getReg(0));
2023 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2035 if (SizeOp0 % NarrowSize != 0)
2037 int NumParts = SizeOp0 / NarrowSize;
2045 for (
int i = 0; i < NumParts; ++i) {
2046 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2061 for (
int i = 0; i < NumParts; ++i) {
2064 PartialExtensionReg = DstRegs.
back();
2066 assert(PartialExtensionReg &&
2067 "Expected to visit partial extension before full");
2068 if (FullExtensionReg) {
2073 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2075 FullExtensionReg = DstRegs.
back();
2080 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2083 PartialExtensionReg = DstRegs.
back();
2089 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2090 MI.eraseFromParent();
2093 case TargetOpcode::G_BSWAP:
2094 case TargetOpcode::G_BITREVERSE: {
2095 if (SizeOp0 % NarrowSize != 0)
2100 unsigned NumParts = SizeOp0 / NarrowSize;
2101 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2104 for (
unsigned i = 0; i < NumParts; ++i) {
2105 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2106 {SrcRegs[NumParts - 1 - i]});
2110 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2113 MI.eraseFromParent();
2116 case TargetOpcode::G_PTR_ADD:
2117 case TargetOpcode::G_PTRMASK: {
2125 case TargetOpcode::G_FPTOUI:
2126 case TargetOpcode::G_FPTOSI:
2127 case TargetOpcode::G_FPTOUI_SAT:
2128 case TargetOpcode::G_FPTOSI_SAT:
2130 case TargetOpcode::G_FPEXT:
2137 case TargetOpcode::G_FLDEXP:
2138 case TargetOpcode::G_STRICT_FLDEXP:
2140 case TargetOpcode::G_VSCALE: {
2142 LLT Ty = MRI.getType(Dst);
2146 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2147 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2148 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2151 MI.eraseFromParent();
2158 LLT Ty = MRI.getType(Val);
2159 if (Ty.isScalar() && !Ty.isFloat())
2166 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2168 if (Ty.isPointer()) {
2169 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2171 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2177 if (Ty.isPointerVector())
2178 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2179 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2183 unsigned OpIdx,
unsigned ExtOpcode) {
2185 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2186 MO.
setReg(ExtB.getReg(0));
2192 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2194 MO.
setReg(ExtB.getReg(0));
2200 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2201 MO.
setReg(ExtB.getReg(0));
2205 unsigned OpIdx,
unsigned TruncOpcode) {
2207 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2209 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2216 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2218 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2223 unsigned OpIdx,
unsigned ExtOpcode) {
2225 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2227 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2236 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2238 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2244 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2254 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2261LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2266 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2267 if (DstTy.isVector())
2272 const int SrcSize = SrcTy.getSizeInBits();
2274 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2276 unsigned NumOps =
MI.getNumOperands();
2277 unsigned NumSrc =
MI.getNumOperands() - 1;
2278 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2280 if (WideSize >= DstSize) {
2284 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2285 const unsigned Offset = (
I - 1) * PartSize;
2298 ResultReg = NextResult;
2301 if (WideSize > DstSize)
2303 else if (DstTy.isPointer())
2305 else if (DstTy != WideTy)
2308 MI.eraseFromParent();
2333 const int GCD = std::gcd(SrcSize, WideSize);
2343 if (GCD == SrcSize) {
2346 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2347 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2353 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2355 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2359 const int PartsPerGCD = WideSize / GCD;
2363 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2365 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2372 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2374 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2375 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2378 MI.eraseFromParent();
2383LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2388 int NumDst =
MI.getNumOperands() - 1;
2389 Register SrcReg =
MI.getOperand(NumDst).getReg();
2390 LLT SrcTy = MRI.getType(SrcReg);
2394 Register Dst0Reg =
MI.getOperand(0).getReg();
2395 LLT DstTy = MRI.getType(Dst0Reg);
2404 dbgs() <<
"Not casting non-integral address space integer\n");
2409 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2417 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2426 SrcTy = MRI.getType(SrcReg);
2430 for (
int I = 1;
I != NumDst; ++
I) {
2431 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2432 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2436 MI.eraseFromParent();
2447 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2451 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2454 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2472 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2477 if (PartsPerRemerge == 1) {
2480 for (
int I = 0;
I != NumUnmerge; ++
I) {
2481 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2483 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2484 int Idx =
I * PartsPerUnmerge + J;
2486 MIB.addDef(
MI.getOperand(Idx).getReg());
2489 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2493 MIB.addUse(Unmerge.getReg(
I));
2496 SmallVector<Register, 16> Parts;
2497 for (
int J = 0; J != NumUnmerge; ++J)
2498 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2501 for (
int I = 0;
I != NumDst; ++
I) {
2502 for (
int J = 0; J < PartsPerRemerge; ++J) {
2503 const int Idx =
I * PartsPerRemerge + J;
2507 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2508 RemergeParts.
clear();
2512 MI.eraseFromParent();
2517LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2519 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2520 unsigned Offset =
MI.getOperand(2).getImm();
2523 if (SrcTy.
isVector() || DstTy.isVector())
2535 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2539 if (DstTy.isPointer())
2546 MI.eraseFromParent();
2551 LLT ShiftTy = SrcTy;
2560 MI.eraseFromParent();
2591LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2593 if (TypeIdx != 0 || WideTy.
isVector())
2603LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2607 std::optional<Register> CarryIn;
2608 switch (
MI.getOpcode()) {
2611 case TargetOpcode::G_SADDO:
2612 Opcode = TargetOpcode::G_ADD;
2613 ExtOpcode = TargetOpcode::G_SEXT;
2615 case TargetOpcode::G_SSUBO:
2616 Opcode = TargetOpcode::G_SUB;
2617 ExtOpcode = TargetOpcode::G_SEXT;
2619 case TargetOpcode::G_UADDO:
2620 Opcode = TargetOpcode::G_ADD;
2621 ExtOpcode = TargetOpcode::G_ZEXT;
2623 case TargetOpcode::G_USUBO:
2624 Opcode = TargetOpcode::G_SUB;
2625 ExtOpcode = TargetOpcode::G_ZEXT;
2627 case TargetOpcode::G_SADDE:
2628 Opcode = TargetOpcode::G_UADDE;
2629 ExtOpcode = TargetOpcode::G_SEXT;
2630 CarryIn =
MI.getOperand(4).getReg();
2632 case TargetOpcode::G_SSUBE:
2633 Opcode = TargetOpcode::G_USUBE;
2634 ExtOpcode = TargetOpcode::G_SEXT;
2635 CarryIn =
MI.getOperand(4).getReg();
2637 case TargetOpcode::G_UADDE:
2638 Opcode = TargetOpcode::G_UADDE;
2639 ExtOpcode = TargetOpcode::G_ZEXT;
2640 CarryIn =
MI.getOperand(4).getReg();
2642 case TargetOpcode::G_USUBE:
2643 Opcode = TargetOpcode::G_USUBE;
2644 ExtOpcode = TargetOpcode::G_ZEXT;
2645 CarryIn =
MI.getOperand(4).getReg();
2661 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2662 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2666 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2668 .buildInstr(Opcode, {WideTy, CarryOutTy},
2669 {LHSExt, RHSExt, *CarryIn})
2672 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2674 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2675 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2676 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2681 MI.eraseFromParent();
2686LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2688 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2689 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2690 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2691 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2692 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2705 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2712 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2716 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2717 {ShiftL, ShiftR},
MI.getFlags());
2722 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2725 MI.eraseFromParent();
2730LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2739 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2741 LLT SrcTy = MRI.getType(
LHS);
2742 LLT OverflowTy = MRI.getType(OriginalOverflow);
2749 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2750 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2751 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2758 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2760 MachineInstrBuilder Mulo;
2761 if (WideMulCanOverflow)
2762 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2763 {LeftOperand, RightOperand});
2765 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2770 MachineInstrBuilder ExtResult;
2777 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2781 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2784 if (WideMulCanOverflow) {
2792 MI.eraseFromParent();
2798 unsigned Opcode =
MI.getOpcode();
2802 case TargetOpcode::G_ATOMICRMW_XCHG:
2803 case TargetOpcode::G_ATOMICRMW_ADD:
2804 case TargetOpcode::G_ATOMICRMW_SUB:
2805 case TargetOpcode::G_ATOMICRMW_AND:
2806 case TargetOpcode::G_ATOMICRMW_OR:
2807 case TargetOpcode::G_ATOMICRMW_XOR:
2808 case TargetOpcode::G_ATOMICRMW_MIN:
2809 case TargetOpcode::G_ATOMICRMW_MAX:
2810 case TargetOpcode::G_ATOMICRMW_UMIN:
2811 case TargetOpcode::G_ATOMICRMW_UMAX:
2812 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2818 case TargetOpcode::G_ATOMIC_CMPXCHG:
2819 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2826 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2836 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2841 case TargetOpcode::G_EXTRACT:
2842 return widenScalarExtract(
MI, TypeIdx, WideTy);
2843 case TargetOpcode::G_INSERT:
2844 return widenScalarInsert(
MI, TypeIdx, WideTy);
2845 case TargetOpcode::G_MERGE_VALUES:
2846 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2847 case TargetOpcode::G_UNMERGE_VALUES:
2848 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2849 case TargetOpcode::G_SADDO:
2850 case TargetOpcode::G_SSUBO:
2851 case TargetOpcode::G_UADDO:
2852 case TargetOpcode::G_USUBO:
2853 case TargetOpcode::G_SADDE:
2854 case TargetOpcode::G_SSUBE:
2855 case TargetOpcode::G_UADDE:
2856 case TargetOpcode::G_USUBE:
2857 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2858 case TargetOpcode::G_UMULO:
2859 case TargetOpcode::G_SMULO:
2860 return widenScalarMulo(
MI, TypeIdx, WideTy);
2861 case TargetOpcode::G_SADDSAT:
2862 case TargetOpcode::G_SSUBSAT:
2863 case TargetOpcode::G_SSHLSAT:
2864 case TargetOpcode::G_UADDSAT:
2865 case TargetOpcode::G_USUBSAT:
2866 case TargetOpcode::G_USHLSAT:
2867 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2868 case TargetOpcode::G_CTTZ:
2869 case TargetOpcode::G_CTTZ_ZERO_POISON:
2870 case TargetOpcode::G_CTLZ:
2871 case TargetOpcode::G_CTLZ_ZERO_POISON:
2872 case TargetOpcode::G_CTLS:
2873 case TargetOpcode::G_CTPOP: {
2886 case TargetOpcode::G_CTTZ:
2887 case TargetOpcode::G_CTTZ_ZERO_POISON:
2888 case TargetOpcode::G_CTLZ_ZERO_POISON:
2889 ExtOpc = TargetOpcode::G_ANYEXT;
2891 case TargetOpcode::G_CTLS:
2892 ExtOpc = TargetOpcode::G_SEXT;
2895 ExtOpc = TargetOpcode::G_ZEXT;
2898 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2899 LLT CurTy = MRI.getType(SrcReg);
2900 unsigned NewOpc = Opcode;
2901 if (NewOpc == TargetOpcode::G_CTTZ) {
2908 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2910 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2916 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2926 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2928 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2933 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2934 Opcode == TargetOpcode::G_CTLZ
2939 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2940 MI.eraseFromParent();
2943 case TargetOpcode::G_BSWAP: {
2947 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2948 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2949 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2952 MI.getOperand(0).setReg(DstExt);
2956 LLT Ty = MRI.getType(DstReg);
2958 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2959 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2965 case TargetOpcode::G_BITREVERSE: {
2969 LLT Ty = MRI.getType(DstReg);
2972 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2974 MI.getOperand(0).setReg(DstExt);
2977 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2978 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2983 case TargetOpcode::G_FREEZE:
2984 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2991 case TargetOpcode::G_ABS:
2998 case TargetOpcode::G_ADD:
2999 case TargetOpcode::G_AND:
3000 case TargetOpcode::G_MUL:
3001 case TargetOpcode::G_OR:
3002 case TargetOpcode::G_XOR:
3003 case TargetOpcode::G_SUB:
3004 case TargetOpcode::G_SHUFFLE_VECTOR:
3020 case TargetOpcode::G_SBFX:
3021 case TargetOpcode::G_UBFX:
3035 case TargetOpcode::G_SHL:
3055 case TargetOpcode::G_ROTR:
3056 case TargetOpcode::G_ROTL:
3065 case TargetOpcode::G_SDIV:
3066 case TargetOpcode::G_SREM:
3067 case TargetOpcode::G_SMIN:
3068 case TargetOpcode::G_SMAX:
3069 case TargetOpcode::G_ABDS:
3077 case TargetOpcode::G_SDIVREM:
3087 case TargetOpcode::G_ASHR:
3088 case TargetOpcode::G_LSHR:
3092 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3093 : TargetOpcode::G_ZEXT;
3106 case TargetOpcode::G_UDIV:
3107 case TargetOpcode::G_UREM:
3108 case TargetOpcode::G_ABDU:
3115 case TargetOpcode::G_UDIVREM:
3124 case TargetOpcode::G_UMIN:
3125 case TargetOpcode::G_UMAX: {
3126 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3128 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3132 ? TargetOpcode::G_SEXT
3133 : TargetOpcode::G_ZEXT;
3143 case TargetOpcode::G_SELECT:
3153 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3160 case TargetOpcode::G_FPEXT:
3168 case TargetOpcode::G_FPTOSI:
3169 case TargetOpcode::G_FPTOUI:
3170 case TargetOpcode::G_INTRINSIC_LRINT:
3171 case TargetOpcode::G_INTRINSIC_LLRINT:
3172 case TargetOpcode::G_IS_FPCLASS:
3182 case TargetOpcode::G_SITOFP:
3192 case TargetOpcode::G_UITOFP:
3202 case TargetOpcode::G_FPTOSI_SAT:
3203 case TargetOpcode::G_FPTOUI_SAT:
3208 LLT Ty = MRI.getType(OldDst);
3209 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3211 MI.getOperand(0).setReg(ExtReg);
3212 uint64_t ShortBits = Ty.getScalarSizeInBits();
3215 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3226 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3227 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3235 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3243 case TargetOpcode::G_LOAD:
3244 case TargetOpcode::G_SEXTLOAD:
3245 case TargetOpcode::G_ZEXTLOAD:
3246 case TargetOpcode::G_FPEXTLOAD:
3252 case TargetOpcode::G_STORE: {
3256 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3257 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3258 if (!Ty.isScalar()) {
3266 MI.setMemRefs(MF, {NewMMO});
3273 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3274 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3280 case TargetOpcode::G_FPTRUNCSTORE:
3287 case TargetOpcode::G_CONSTANT: {
3290 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3291 MRI.getType(
MI.getOperand(0).getReg()));
3292 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3293 ExtOpc == TargetOpcode::G_ANYEXT) &&
3296 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3300 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3306 case TargetOpcode::G_FCONSTANT: {
3312 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3314 MI.eraseFromParent();
3317 case TargetOpcode::G_IMPLICIT_DEF: {
3323 case TargetOpcode::G_BRCOND:
3329 case TargetOpcode::G_FCMP:
3340 case TargetOpcode::G_ICMP:
3345 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3349 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3350 unsigned ExtOpcode =
3354 ? TargetOpcode::G_SEXT
3355 : TargetOpcode::G_ZEXT;
3362 case TargetOpcode::G_PTR_ADD:
3363 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3369 case TargetOpcode::G_PHI: {
3370 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3373 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3385 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3388 LLT VecTy = MRI.getType(VecReg);
3392 TargetOpcode::G_ANYEXT);
3406 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3422 LLT VecTy = MRI.getType(VecReg);
3441 case TargetOpcode::G_FADD:
3442 case TargetOpcode::G_FMUL:
3443 case TargetOpcode::G_FSUB:
3444 case TargetOpcode::G_FMA:
3445 case TargetOpcode::G_FMAD:
3446 case TargetOpcode::G_FNEG:
3447 case TargetOpcode::G_FABS:
3448 case TargetOpcode::G_FCANONICALIZE:
3449 case TargetOpcode::G_FMINNUM:
3450 case TargetOpcode::G_FMAXNUM:
3451 case TargetOpcode::G_FMINNUM_IEEE:
3452 case TargetOpcode::G_FMAXNUM_IEEE:
3453 case TargetOpcode::G_FMINIMUM:
3454 case TargetOpcode::G_FMAXIMUM:
3455 case TargetOpcode::G_FMINIMUMNUM:
3456 case TargetOpcode::G_FMAXIMUMNUM:
3457 case TargetOpcode::G_FDIV:
3458 case TargetOpcode::G_FREM:
3459 case TargetOpcode::G_FCEIL:
3460 case TargetOpcode::G_FFLOOR:
3461 case TargetOpcode::G_FCOS:
3462 case TargetOpcode::G_FSIN:
3463 case TargetOpcode::G_FTAN:
3464 case TargetOpcode::G_FACOS:
3465 case TargetOpcode::G_FASIN:
3466 case TargetOpcode::G_FATAN:
3467 case TargetOpcode::G_FATAN2:
3468 case TargetOpcode::G_FCOSH:
3469 case TargetOpcode::G_FSINH:
3470 case TargetOpcode::G_FTANH:
3471 case TargetOpcode::G_FLOG10:
3472 case TargetOpcode::G_FLOG:
3473 case TargetOpcode::G_FLOG2:
3474 case TargetOpcode::G_FRINT:
3475 case TargetOpcode::G_FNEARBYINT:
3476 case TargetOpcode::G_FSQRT:
3477 case TargetOpcode::G_FEXP:
3478 case TargetOpcode::G_FEXP2:
3479 case TargetOpcode::G_FEXP10:
3480 case TargetOpcode::G_FPOW:
3481 case TargetOpcode::G_INTRINSIC_TRUNC:
3482 case TargetOpcode::G_INTRINSIC_ROUND:
3483 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3487 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3493 case TargetOpcode::G_FMODF: {
3503 case TargetOpcode::G_FPOWI:
3504 case TargetOpcode::G_FLDEXP:
3505 case TargetOpcode::G_STRICT_FLDEXP: {
3507 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3528 case TargetOpcode::G_FFREXP: {
3541 case TargetOpcode::G_LROUND:
3542 case TargetOpcode::G_LLROUND:
3553 case TargetOpcode::G_INTTOPTR:
3561 case TargetOpcode::G_PTRTOINT:
3569 case TargetOpcode::G_BUILD_VECTOR: {
3573 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3579 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3587 case TargetOpcode::G_SEXT_INREG:
3596 case TargetOpcode::G_PTRMASK: {
3604 case TargetOpcode::G_VECREDUCE_ADD: {
3613 case TargetOpcode::G_VECREDUCE_FADD:
3614 case TargetOpcode::G_VECREDUCE_FMUL:
3615 case TargetOpcode::G_VECREDUCE_FMIN:
3616 case TargetOpcode::G_VECREDUCE_FMAX:
3617 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3618 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3623 LLT VecTy = MRI.getType(VecReg);
3630 case TargetOpcode::G_VSCALE: {
3637 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3642 case TargetOpcode::G_SPLAT_VECTOR: {
3651 case TargetOpcode::G_INSERT_SUBVECTOR: {
3659 LLT SubVecTy = MRI.getType(SubVec);
3663 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3664 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3665 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3669 auto SplatZero =
MIRBuilder.buildSplatVector(
3674 MI.eraseFromParent();
3678 case TargetOpcode::G_BITCAST:
3690 if (MRI.getType(Dst) == MRI.getType(Src)) {
3691 Observer.changingAllUsesOfReg(MRI, Dst);
3692 MRI.replaceRegWith(Dst, Src);
3693 Observer.finishedChangingAllUsesOfReg();
3694 MI.eraseFromParent();
3703 auto Unmerge =
B.buildUnmerge(Ty, Src);
3704 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3713 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3727 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3736 MI.eraseFromParent();
3747 MI.eraseFromParent();
3754 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3755 if (SrcTy.isVector()) {
3759 if (DstTy.isVector()) {
3760 int NumDstElt = DstTy.getNumElements();
3761 int NumSrcElt = SrcTy.getNumElements();
3764 LLT DstCastTy = DstEltTy;
3765 LLT SrcPartTy = SrcEltTy;
3769 if (NumSrcElt < NumDstElt) {
3780 SrcPartTy = SrcEltTy;
3781 }
else if (NumSrcElt > NumDstElt) {
3793 DstCastTy = DstEltTy;
3798 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3802 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3803 MI.eraseFromParent();
3807 if (DstTy.isVector()) {
3810 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3811 MI.eraseFromParent();
3827 unsigned NewEltSize,
3828 unsigned OldEltSize) {
3829 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3830 LLT IdxTy =
B.getMRI()->getType(Idx);
3833 auto OffsetMask =
B.buildConstant(
3835 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3836 return B.buildShl(IdxTy, OffsetIdx,
3837 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3852 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3856 unsigned OldNumElts = SrcVecTy.getNumElements();
3863 if (NewNumElts > OldNumElts) {
3874 if (NewNumElts % OldNumElts != 0)
3878 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3882 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3885 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3887 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3888 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3889 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3890 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3891 NewOps[
I] = Elt.getReg(0);
3894 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3896 MI.eraseFromParent();
3900 if (NewNumElts < OldNumElts) {
3901 if (NewEltSize % OldEltSize != 0)
3923 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3924 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3927 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3931 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3932 ScaledIdx).getReg(0);
3940 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3942 MI.eraseFromParent();
3956 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3957 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3958 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3959 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3962 auto EltMask =
B.buildConstant(
3966 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3967 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3970 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3974 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3988 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3989 MI.getFirst4RegLLTs();
4001 if (NewNumElts < OldNumElts) {
4002 if (NewEltSize % OldEltSize != 0)
4011 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4012 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4015 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4019 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4020 ScaledIdx).getReg(0);
4030 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4031 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4035 MI.eraseFromParent();
4065 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4069 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4070 return UnableToLegalize;
4075 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4077 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4086 MI.eraseFromParent();
4104 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4105 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4115 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4116 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4118 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4119 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4121 MI.eraseFromParent();
4147 uint64_t Idx = ES->getIndexImm();
4151 LLT DstTy = MRI.getType(Dst);
4152 LLT SrcTy = MRI.getType(Src);
4158 if (DstTy == CastTy)
4166 if (CastEltSize < DstEltSize)
4169 auto AdjustAmt = CastEltSize / DstEltSize;
4170 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4171 SrcTyMinElts % AdjustAmt != 0)
4176 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4177 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4180 ES->eraseFromParent();
4211 uint64_t Idx = ES->getIndexImm();
4215 LLT DstTy = MRI.getType(Dst);
4216 LLT BigVecTy = MRI.getType(BigVec);
4217 LLT SubVecTy = MRI.getType(SubVec);
4219 if (DstTy == CastTy)
4234 if (CastEltSize < DstEltSize)
4237 auto AdjustAmt = CastEltSize / DstEltSize;
4238 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4239 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4245 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4246 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4248 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4251 ES->eraseFromParent();
4259 LLT DstTy = MRI.getType(DstReg);
4269 if (MemSizeInBits != MemStoreSizeInBits) {
4286 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4290 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4291 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4293 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4296 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4298 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4301 if (DstTy != LoadTy)
4309 if (
MIRBuilder.getDataLayout().isBigEndian())
4327 uint64_t LargeSplitSize, SmallSplitSize;
4332 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4339 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4342 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4353 if (Alignment.value() * 8 > MemSizeInBits &&
4358 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4375 LLT PtrTy = MRI.getType(PtrReg);
4388 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4391 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4392 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4393 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4395 SmallPtr, *SmallMMO);
4397 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4398 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4400 if (AnyExtTy == DstTy)
4401 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4403 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4407 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4427 LLT SrcTy = MRI.getType(SrcReg);
4435 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4441 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4443 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4447 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4451 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4466 uint64_t LargeSplitSize, SmallSplitSize;
4473 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4476 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4485 if (SrcTy.isPointer()) {
4490 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4493 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4494 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4497 LLT PtrTy = MRI.getType(PtrReg);
4499 LargeSplitSize / 8);
4500 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4506 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4507 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4516 LLT SrcTy = MRI.getType(SrcReg);
4522 assert(SrcTy.isVector() &&
"Expect a vector store type");
4529 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4533 auto Elt =
MIRBuilder.buildExtractVectorElement(
4534 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4535 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4536 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4542 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4543 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4547 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4558 switch (
MI.getOpcode()) {
4559 case TargetOpcode::G_LOAD: {
4577 case TargetOpcode::G_STORE: {
4593 case TargetOpcode::G_SELECT: {
4597 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4599 dbgs() <<
"bitcast action not implemented for vector select\n");
4610 case TargetOpcode::G_AND:
4611 case TargetOpcode::G_OR:
4612 case TargetOpcode::G_XOR: {
4620 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4622 case TargetOpcode::G_INSERT_VECTOR_ELT:
4624 case TargetOpcode::G_CONCAT_VECTORS:
4626 case TargetOpcode::G_SHUFFLE_VECTOR:
4628 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4630 case TargetOpcode::G_INSERT_SUBVECTOR:
4638void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4647 switch(
MI.getOpcode()) {
4650 case TargetOpcode::G_FCONSTANT:
4652 case TargetOpcode::G_BITCAST:
4654 case TargetOpcode::G_SREM:
4655 case TargetOpcode::G_UREM: {
4656 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4658 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4659 {MI.getOperand(1), MI.getOperand(2)});
4661 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4663 MI.eraseFromParent();
4666 case TargetOpcode::G_SADDO:
4667 case TargetOpcode::G_SSUBO:
4669 case TargetOpcode::G_SADDE:
4671 case TargetOpcode::G_SSUBE:
4673 case TargetOpcode::G_UMULH:
4674 case TargetOpcode::G_SMULH:
4676 case TargetOpcode::G_SMULO:
4677 case TargetOpcode::G_UMULO: {
4680 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4681 LLT Ty = MRI.getType(Res);
4683 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4684 ? TargetOpcode::G_SMULH
4685 : TargetOpcode::G_UMULH;
4689 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4690 MI.removeOperand(1);
4693 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4701 if (Opcode == TargetOpcode::G_SMULH) {
4702 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4703 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4710 case TargetOpcode::G_FNEG: {
4711 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4714 Register CastedSubByReg = SubByReg;
4716 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4717 !SubByRegTy.getScalarType().isInteger()) {
4718 auto BitcastDst = SubByRegTy.changeElementType(
4720 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4726 if (ResTy != TyInt) {
4728 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4731 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4733 MI.eraseFromParent();
4736 case TargetOpcode::G_FSUB:
4737 case TargetOpcode::G_STRICT_FSUB: {
4738 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4739 LLT Ty = MRI.getType(Res);
4744 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4745 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4749 MI.eraseFromParent();
4752 case TargetOpcode::G_FMAD:
4754 case TargetOpcode::G_FFLOOR:
4756 case TargetOpcode::G_LROUND:
4757 case TargetOpcode::G_LLROUND: {
4760 LLT SrcTy = MRI.getType(SrcReg);
4761 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4764 MI.eraseFromParent();
4767 case TargetOpcode::G_INTRINSIC_ROUND:
4769 case TargetOpcode::G_FRINT: {
4772 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4775 case TargetOpcode::G_INTRINSIC_LRINT:
4776 case TargetOpcode::G_INTRINSIC_LLRINT: {
4779 LLT SrcTy = MRI.getType(SrcReg);
4781 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4783 MI.eraseFromParent();
4786 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4787 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4788 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4789 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4790 **
MI.memoperands_begin());
4792 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4793 MI.eraseFromParent();
4796 case TargetOpcode::G_LOAD:
4797 case TargetOpcode::G_SEXTLOAD:
4798 case TargetOpcode::G_ZEXTLOAD:
4800 case TargetOpcode::G_STORE:
4802 case TargetOpcode::G_CTLZ_ZERO_POISON:
4803 case TargetOpcode::G_CTTZ_ZERO_POISON:
4804 case TargetOpcode::G_CTLZ:
4805 case TargetOpcode::G_CTTZ:
4806 case TargetOpcode::G_CTPOP:
4807 case TargetOpcode::G_CTLS:
4810 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4812 Register NewRes = MRI.cloneVirtualRegister(Res);
4819 MI.eraseFromParent();
4823 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4824 const LLT CondTy = MRI.getType(CarryOut);
4825 const LLT Ty = MRI.getType(Res);
4827 Register NewRes = MRI.cloneVirtualRegister(Res);
4830 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4836 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4837 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4844 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4849 MI.eraseFromParent();
4853 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4858 MI.eraseFromParent();
4862 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4863 const LLT CondTy = MRI.getType(BorrowOut);
4864 const LLT Ty = MRI.getType(Res);
4867 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4873 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4874 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4881 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4882 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4884 MI.eraseFromParent();
4924 case G_MERGE_VALUES:
4926 case G_UNMERGE_VALUES:
4928 case TargetOpcode::G_SEXT_INREG: {
4929 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4930 int64_t SizeInBits =
MI.getOperand(2).getImm();
4932 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4933 LLT DstTy = MRI.getType(DstReg);
4934 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4937 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4938 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4939 MI.eraseFromParent();
4942 case G_EXTRACT_VECTOR_ELT:
4943 case G_INSERT_VECTOR_ELT:
4945 case G_SHUFFLE_VECTOR:
4947 case G_VECTOR_COMPRESS:
4949 case G_DYN_STACKALLOC:
4951 case G_INSERT_SUBVECTOR: {
4952 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4953 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4958 Register Subvector =
MI.getOperand(2).getReg();
4959 auto InsertionPointImm =
MI.getOperand(3).getImm();
4962 LLT DstTy = MRI.getType(Subvector);
4966 bool InsertInLowHalf = InsertionPointImm == 0;
4967 auto Extract =
MIRBuilder.buildExtractSubvector(
4969 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
4971 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4972 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4974 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4975 {LowHalf, HighHalf});
4976 MI.eraseFromParent();
4982 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4983 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4989 if (i >= InsertionPointImm &&
4991 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
4999 MI.eraseFromParent();
5003 case G_EXTRACT_SUBVECTOR: {
5006 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5008 LLT SrcTy = MRI.getType(SrcReg);
5009 LLT DstTy = MRI.getType(DstReg);
5011 if (SrcTy.isScalable() || DstTy.
isScalable())
5022 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5023 ExtractionPointImm + i)
5027 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5028 MI.eraseFromParent();
5033 case G_STACKRESTORE:
5043 case G_READ_REGISTER:
5044 case G_WRITE_REGISTER:
5051 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5052 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5058 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5063 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5070 case G_TRUNC_SSAT_S:
5071 case G_TRUNC_USAT_U:
5072 case G_TRUNC_SSAT_U:
5078 bool IsSigned =
MI.getOpcode() == G_ABDS;
5079 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5080 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5081 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5104 case G_MEMCPY_INLINE:
5105 case G_MEMSET_INLINE:
5117 case G_ATOMICRMW_SUB: {
5118 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5119 const LLT ValTy = MRI.getType(Val);
5123 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5124 MI.eraseFromParent();
5152 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5156 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5162 Align StackTypeAlign =
5169 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5170 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5175 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5187 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5190 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5201 "Converting bits to bytes lost precision");
5207 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5208 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5210 if (IdxTy != MRI.getType(Index))
5211 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5216 LLT PtrTy = MRI.getType(VecPtr);
5217 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5225 std::initializer_list<unsigned> NonVecOpIndices) {
5226 if (
MI.getNumMemOperands() != 0)
5234 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5243 if (!Ty.isVector()) {
5249 if (Ty.getNumElements() != NumElts)
5264 assert(Ty.isVector() &&
"Expected vector type");
5266 int NumParts, NumLeftover;
5267 std::tie(NumParts, NumLeftover) =
5270 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5271 for (
int i = 0; i < NumParts; ++i) {
5276 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5285 for (
unsigned i = 0; i <
N; ++i) {
5287 Ops.push_back(
Op.getReg());
5288 else if (
Op.isImm())
5289 Ops.push_back(
Op.getImm());
5290 else if (
Op.isPredicate())
5312 std::initializer_list<unsigned> NonVecOpIndices) {
5314 "Non-compatible opcode or not specified non-vector operands");
5315 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5317 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5318 unsigned NumDefs =
MI.getNumDefs();
5326 for (
unsigned i = 0; i < NumDefs; ++i) {
5327 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5335 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5336 ++UseIdx, ++UseNo) {
5339 MI.getOperand(UseIdx));
5348 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5352 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5354 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5355 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5358 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5359 Uses.push_back(InputOpsPieces[InputNo][i]);
5362 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5363 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5368 for (
unsigned i = 0; i < NumDefs; ++i)
5369 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5371 for (
unsigned i = 0; i < NumDefs; ++i)
5372 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5375 MI.eraseFromParent();
5382 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5384 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5385 unsigned NumDefs =
MI.getNumDefs();
5389 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5394 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5395 UseIdx += 2, ++UseNo) {
5403 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5405 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5406 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5408 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5411 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5412 Phi.addUse(InputOpsPieces[j][i]);
5413 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5423 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5425 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5428 MI.eraseFromParent();
5436 const int NumDst =
MI.getNumOperands() - 1;
5437 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5438 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5439 LLT SrcTy = MRI.getType(SrcReg);
5441 if (TypeIdx != 1 || NarrowTy == DstTy)
5448 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5451 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5465 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5466 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5467 const int PartsPerUnmerge = NumDst / NumUnmerge;
5469 for (
int I = 0;
I != NumUnmerge; ++
I) {
5470 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5472 for (
int J = 0; J != PartsPerUnmerge; ++J)
5473 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5474 MIB.addUse(Unmerge.getReg(
I));
5477 MI.eraseFromParent();
5484 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5488 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5490 if (NarrowTy == SrcTy)
5498 assert(SrcTy.isVector() &&
"Expected vector types");
5500 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5514 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5515 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5516 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5522 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5523 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5524 ++i,
Offset += NumNarrowTyElts) {
5527 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5530 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5531 MI.eraseFromParent();
5535 assert(TypeIdx == 0 &&
"Bad type index");
5536 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5551 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5552 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5554 for (
unsigned i = 0; i < NumParts; ++i) {
5556 for (
unsigned j = 0; j < NumElts; ++j)
5557 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5559 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5562 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5563 MI.eraseFromParent();
5571 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5573 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5575 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5577 InsertVal =
MI.getOperand(2).getReg();
5579 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5580 LLT VecTy = MRI.getType(SrcVec);
5586 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5590 MI.eraseFromParent();
5599 SplitPieces[IdxVal] = InsertVal;
5600 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5602 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5606 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5609 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5610 TargetOpcode::G_ANYEXT);
5614 LLT IdxTy = MRI.getType(Idx);
5615 int64_t PartIdx = IdxVal / NewNumElts;
5617 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5620 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5623 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5624 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5625 VecParts[PartIdx] = InsertPart.getReg(0);
5629 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5631 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5635 MI.eraseFromParent();
5655 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5667 LLT ValTy = MRI.getType(ValReg);
5676 int NumLeftover = -1;
5682 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5684 NumParts = NarrowRegs.
size();
5685 NumLeftover = NarrowLeftoverRegs.
size();
5692 LLT PtrTy = MRI.getType(AddrReg);
5702 auto MMO = LdStMI.
getMMO();
5704 unsigned NumParts,
unsigned Offset) ->
unsigned {
5707 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5709 unsigned ByteOffset =
Offset / 8;
5712 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5719 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5720 ValRegs.push_back(Dst);
5721 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5723 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5732 unsigned HandledOffset =
5733 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5737 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5740 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5741 LeftoverTy, NarrowLeftoverRegs);
5755 switch (
MI.getOpcode()) {
5756 case G_IMPLICIT_DEF:
5772 case G_FCANONICALIZE:
5789 case G_INTRINSIC_LRINT:
5790 case G_INTRINSIC_LLRINT:
5791 case G_INTRINSIC_ROUND:
5792 case G_INTRINSIC_ROUNDEVEN:
5795 case G_INTRINSIC_TRUNC:
5823 case G_FMINNUM_IEEE:
5824 case G_FMAXNUM_IEEE:
5846 case G_CTLZ_ZERO_POISON:
5848 case G_CTTZ_ZERO_POISON:
5865 case G_ADDRSPACE_CAST:
5878 case G_STRICT_FLDEXP:
5880 case G_TRUNC_SSAT_S:
5881 case G_TRUNC_SSAT_U:
5882 case G_TRUNC_USAT_U:
5890 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5895 case G_UNMERGE_VALUES:
5897 case G_BUILD_VECTOR:
5898 assert(TypeIdx == 0 &&
"not a vector type index");
5900 case G_CONCAT_VECTORS:
5904 case G_EXTRACT_SUBVECTOR: {
5906 LLT DstTy = MRI.getType(DstReg);
5908 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5918 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5919 uint64_t RequiredSubvectorIndex =
5923 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5926 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5929 MI.eraseFromParent();
5932 case G_EXTRACT_VECTOR_ELT:
5933 case G_INSERT_VECTOR_ELT:
5942 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5943 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5945 case G_SHUFFLE_VECTOR:
5951 case G_INTRINSIC_FPTRUNC_ROUND:
5961 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5962 "Not a bitcast operation");
5967 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5969 unsigned NewElemCount =
5972 if (NewElemCount == 1) {
5975 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5982 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5991 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5992 MI.eraseFromParent();
5998 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6002 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6003 MI.getFirst3RegLLTs();
6006 if (DstTy != Src1Ty)
6008 if (DstTy != Src2Ty)
6023 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6039 unsigned InputUsed[2] = {-1U, -1U};
6040 unsigned FirstMaskIdx =
High * NewElts;
6041 bool UseBuildVector =
false;
6042 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6044 int Idx = Mask[FirstMaskIdx + MaskOffset];
6049 if (
Input >= std::size(Inputs)) {
6056 Idx -=
Input * NewElts;
6060 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6061 if (InputUsed[OpNo] ==
Input) {
6064 }
else if (InputUsed[OpNo] == -1U) {
6066 InputUsed[OpNo] =
Input;
6071 if (OpNo >= std::size(InputUsed)) {
6074 UseBuildVector =
true;
6079 Ops.push_back(Idx + OpNo * NewElts);
6082 if (UseBuildVector) {
6087 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6089 int Idx = Mask[FirstMaskIdx + MaskOffset];
6094 if (
Input >= std::size(Inputs)) {
6101 Idx -=
Input * NewElts;
6105 .buildExtractVectorElement(
6106 EltTy, Inputs[
Input],
6112 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6113 }
else if (InputUsed[0] == -1U) {
6115 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6116 }
else if (NewElts == 1) {
6117 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6119 Register Op0 = Inputs[InputUsed[0]];
6123 : Inputs[InputUsed[1]];
6125 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6132 MI.eraseFromParent();
6145 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6151 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6154 const unsigned NumParts =
6156 : SrcTy.getNumElements();
6160 if (DstTy != NarrowTy)
6166 unsigned NumPartsLeft = NumParts;
6167 while (NumPartsLeft > 1) {
6168 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6171 .buildInstr(ScalarOpc, {NarrowTy},
6172 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
6175 SplitSrcs = PartialResults;
6176 PartialResults.
clear();
6177 NumPartsLeft = SplitSrcs.
size();
6181 MI.eraseFromParent();
6186 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6187 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
6190 MI.eraseFromParent();
6194 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6196 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
6204 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6207 Register Acc = PartialReductions[0];
6208 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6209 if (Part == NumParts - 1) {
6211 {Acc, PartialReductions[Part]});
6214 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
6218 MI.eraseFromParent();
6224 unsigned int TypeIdx,
6226 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6227 MI.getFirst3RegLLTs();
6228 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6232 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6233 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6234 "Unexpected vecreduce opcode");
6235 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6236 ? TargetOpcode::G_FADD
6237 : TargetOpcode::G_FMUL;
6240 unsigned NumParts = SrcTy.getNumElements();
6243 for (
unsigned i = 0; i < NumParts; i++)
6244 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
6248 MI.eraseFromParent();
6255 unsigned ScalarOpc) {
6263 while (SplitSrcs.
size() > 1) {
6265 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6273 SplitSrcs = std::move(PartialRdxs);
6277 MI.getOperand(1).setReg(SplitSrcs[0]);
6284 const LLT HalfTy,
const LLT AmtTy) {
6286 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6287 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6291 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6292 MI.eraseFromParent();
6298 unsigned VTBits = 2 * NVTBits;
6301 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6302 if (Amt.
ugt(VTBits)) {
6304 }
else if (Amt.
ugt(NVTBits)) {
6307 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6308 }
else if (Amt == NVTBits) {
6316 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6319 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6320 if (Amt.
ugt(VTBits)) {
6322 }
else if (Amt.
ugt(NVTBits)) {
6324 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6326 }
else if (Amt == NVTBits) {
6330 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6332 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6334 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6340 if (Amt.
ugt(VTBits)) {
6342 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6343 }
else if (Amt.
ugt(NVTBits)) {
6345 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6347 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6348 }
else if (Amt == NVTBits) {
6351 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6353 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6355 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6357 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6364 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6365 MI.eraseFromParent();
6381 LLT DstTy = MRI.getType(DstReg);
6386 LLT ShiftAmtTy = MRI.getType(Amt);
6388 if (DstEltSize % 2 != 0)
6404 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6415 const unsigned NewBitSize = DstEltSize / 2;
6427 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6429 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6430 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6433 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6434 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6436 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6441 switch (
MI.getOpcode()) {
6442 case TargetOpcode::G_SHL: {
6444 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6446 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6447 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6448 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6451 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6452 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6454 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6456 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6458 ResultRegs[0] =
Lo.getReg(0);
6459 ResultRegs[1] =
Hi.getReg(0);
6462 case TargetOpcode::G_LSHR:
6463 case TargetOpcode::G_ASHR: {
6465 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6467 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6468 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6469 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6473 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6476 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6477 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6479 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6483 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6485 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6487 ResultRegs[0] =
Lo.getReg(0);
6488 ResultRegs[1] =
Hi.getReg(0);
6495 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6496 MI.eraseFromParent();
6505 LLT TargetTy,
LLT ShiftAmtTy) {
6508 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6510 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6511 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6512 const bool NeedsInterWordShift = ShiftBits != 0;
6515 case TargetOpcode::G_SHL: {
6518 if (PartIdx < ShiftWords)
6521 unsigned SrcIdx = PartIdx - ShiftWords;
6522 if (!NeedsInterWordShift)
6523 return SrcParts[SrcIdx];
6528 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6532 return Hi.getReg(0);
6535 case TargetOpcode::G_LSHR: {
6536 unsigned SrcIdx = PartIdx + ShiftWords;
6537 if (SrcIdx >= NumParts)
6539 if (!NeedsInterWordShift)
6540 return SrcParts[SrcIdx];
6544 if (SrcIdx + 1 < NumParts) {
6545 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6549 return Lo.getReg(0);
6552 case TargetOpcode::G_ASHR: {
6554 unsigned SrcIdx = PartIdx + ShiftWords;
6555 if (SrcIdx >= NumParts)
6557 if (!NeedsInterWordShift)
6558 return SrcParts[SrcIdx];
6563 (SrcIdx == NumParts - 1)
6567 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6589 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6590 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6595 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6604 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6605 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6607 auto IsZeroBitShift =
6615 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6616 : TargetOpcode::G_SHL;
6619 auto TargetBitsConst =
6621 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6626 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6631 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6633 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6637 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6650 LLT DstTy = MRI.getType(DstReg);
6654 const unsigned NumParts = DstBits / TargetBits;
6656 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6666 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6667 MI.eraseFromParent();
6672 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6673 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6679 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6683 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6686 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6687 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6691 for (
unsigned I = 0;
I < NumParts; ++
I)
6693 Params, TargetTy, ShiftAmtTy);
6695 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6696 MI.eraseFromParent();
6705 LLT DstTy = MRI.getType(DstReg);
6706 LLT ShiftAmtTy = MRI.getType(AmtReg);
6710 const unsigned NumParts = DstBits / TargetBits;
6712 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6729 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6741 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6742 auto TargetBitsLog2Const =
6743 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6744 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6747 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6749 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6757 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6758 auto TargetBitsMinusOneConst =
6759 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6761 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6762 TargetBitsMinusOneConst)
6765 FillValue = ZeroReg;
6773 for (
unsigned I = 0;
I < NumParts; ++
I) {
6775 Register InBoundsResult = FillValue;
6785 for (
unsigned K = 0; K < NumParts; ++K) {
6786 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6788 WordShift, WordShiftKConst);
6800 switch (
MI.getOpcode()) {
6801 case TargetOpcode::G_SHL:
6802 MainSrcIdx = (int)
I - (
int)K;
6803 CarrySrcIdx = MainSrcIdx - 1;
6805 case TargetOpcode::G_LSHR:
6806 case TargetOpcode::G_ASHR:
6807 MainSrcIdx = (int)
I + (
int)K;
6808 CarrySrcIdx = MainSrcIdx + 1;
6816 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6817 Register MainOp = SrcParts[MainSrcIdx];
6821 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6822 CarryOp = SrcParts[CarrySrcIdx];
6823 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6824 CarrySrcIdx >= (
int)NumParts)
6825 CarryOp = FillValue;
6831 ResultForK = FillValue;
6837 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6844 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6848 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6849 MI.eraseFromParent();
6856 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6859 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6874 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6879 "getNeutralElementForVecReduce called with invalid opcode!");
6880 case TargetOpcode::G_VECREDUCE_ADD:
6881 case TargetOpcode::G_VECREDUCE_OR:
6882 case TargetOpcode::G_VECREDUCE_XOR:
6883 case TargetOpcode::G_VECREDUCE_UMAX:
6885 case TargetOpcode::G_VECREDUCE_MUL:
6887 case TargetOpcode::G_VECREDUCE_AND:
6888 case TargetOpcode::G_VECREDUCE_UMIN:
6891 case TargetOpcode::G_VECREDUCE_SMAX:
6894 case TargetOpcode::G_VECREDUCE_SMIN:
6897 case TargetOpcode::G_VECREDUCE_FADD:
6899 case TargetOpcode::G_VECREDUCE_FMUL:
6901 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6902 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6903 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6904 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6912 unsigned Opc =
MI.getOpcode();
6914 case TargetOpcode::G_IMPLICIT_DEF:
6915 case TargetOpcode::G_LOAD: {
6923 case TargetOpcode::G_STORE:
6930 case TargetOpcode::G_AND:
6931 case TargetOpcode::G_OR:
6932 case TargetOpcode::G_XOR:
6933 case TargetOpcode::G_ADD:
6934 case TargetOpcode::G_SUB:
6935 case TargetOpcode::G_MUL:
6936 case TargetOpcode::G_FADD:
6937 case TargetOpcode::G_FSUB:
6938 case TargetOpcode::G_FMUL:
6939 case TargetOpcode::G_FDIV:
6940 case TargetOpcode::G_FCOPYSIGN:
6941 case TargetOpcode::G_UADDSAT:
6942 case TargetOpcode::G_USUBSAT:
6943 case TargetOpcode::G_SADDSAT:
6944 case TargetOpcode::G_SSUBSAT:
6945 case TargetOpcode::G_SMIN:
6946 case TargetOpcode::G_SMAX:
6947 case TargetOpcode::G_UMIN:
6948 case TargetOpcode::G_UMAX:
6949 case TargetOpcode::G_FMINNUM:
6950 case TargetOpcode::G_FMAXNUM:
6951 case TargetOpcode::G_FMINNUM_IEEE:
6952 case TargetOpcode::G_FMAXNUM_IEEE:
6953 case TargetOpcode::G_FMINIMUM:
6954 case TargetOpcode::G_FMAXIMUM:
6955 case TargetOpcode::G_FMINIMUMNUM:
6956 case TargetOpcode::G_FMAXIMUMNUM:
6957 case TargetOpcode::G_STRICT_FADD:
6958 case TargetOpcode::G_STRICT_FSUB:
6959 case TargetOpcode::G_STRICT_FMUL: {
6967 case TargetOpcode::G_SHL:
6968 case TargetOpcode::G_ASHR:
6969 case TargetOpcode::G_LSHR: {
6975 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6981 case TargetOpcode::G_FMA:
6982 case TargetOpcode::G_STRICT_FMA:
6983 case TargetOpcode::G_FSHR:
6984 case TargetOpcode::G_FSHL: {
6993 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6994 case TargetOpcode::G_EXTRACT:
7001 case TargetOpcode::G_INSERT:
7002 case TargetOpcode::G_INSERT_VECTOR_ELT:
7003 case TargetOpcode::G_FREEZE:
7004 case TargetOpcode::G_FNEG:
7005 case TargetOpcode::G_FABS:
7006 case TargetOpcode::G_FSQRT:
7007 case TargetOpcode::G_FCEIL:
7008 case TargetOpcode::G_FFLOOR:
7009 case TargetOpcode::G_FNEARBYINT:
7010 case TargetOpcode::G_FRINT:
7011 case TargetOpcode::G_INTRINSIC_ROUND:
7012 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7013 case TargetOpcode::G_INTRINSIC_TRUNC:
7014 case TargetOpcode::G_BITREVERSE:
7015 case TargetOpcode::G_BSWAP:
7016 case TargetOpcode::G_FCANONICALIZE:
7017 case TargetOpcode::G_SEXT_INREG:
7018 case TargetOpcode::G_ABS:
7019 case TargetOpcode::G_CTLZ:
7020 case TargetOpcode::G_CTPOP:
7028 case TargetOpcode::G_SELECT: {
7029 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7031 if (!CondTy.isScalar() ||
7037 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7039 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7044 if (CondTy.isVector())
7054 case TargetOpcode::G_UNMERGE_VALUES:
7056 case TargetOpcode::G_PHI:
7058 case TargetOpcode::G_SHUFFLE_VECTOR:
7060 case TargetOpcode::G_BUILD_VECTOR: {
7062 for (
auto Op :
MI.uses()) {
7070 MIRBuilder.buildDeleteTrailingVectorElements(
7071 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7072 MI.eraseFromParent();
7075 case TargetOpcode::G_SEXT:
7076 case TargetOpcode::G_ZEXT:
7077 case TargetOpcode::G_ANYEXT:
7078 case TargetOpcode::G_TRUNC:
7079 case TargetOpcode::G_FPTRUNC:
7080 case TargetOpcode::G_FPEXT:
7081 case TargetOpcode::G_FPTOSI:
7082 case TargetOpcode::G_FPTOUI:
7083 case TargetOpcode::G_FPTOSI_SAT:
7084 case TargetOpcode::G_FPTOUI_SAT:
7085 case TargetOpcode::G_SITOFP:
7086 case TargetOpcode::G_UITOFP:
7087 case TargetOpcode::G_TRUNC_SSAT_S:
7088 case TargetOpcode::G_TRUNC_SSAT_U:
7089 case TargetOpcode::G_TRUNC_USAT_U: {
7096 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7099 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7107 case TargetOpcode::G_ICMP:
7108 case TargetOpcode::G_FCMP: {
7116 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7121 case TargetOpcode::G_BITCAST: {
7125 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7126 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7142 case TargetOpcode::G_VECREDUCE_FADD:
7143 case TargetOpcode::G_VECREDUCE_FMUL:
7144 case TargetOpcode::G_VECREDUCE_ADD:
7145 case TargetOpcode::G_VECREDUCE_MUL:
7146 case TargetOpcode::G_VECREDUCE_AND:
7147 case TargetOpcode::G_VECREDUCE_OR:
7148 case TargetOpcode::G_VECREDUCE_XOR:
7149 case TargetOpcode::G_VECREDUCE_SMAX:
7150 case TargetOpcode::G_VECREDUCE_SMIN:
7151 case TargetOpcode::G_VECREDUCE_UMAX:
7152 case TargetOpcode::G_VECREDUCE_UMIN: {
7153 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7155 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7156 auto NeutralElement = getNeutralElementForVecReduce(
7162 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7163 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7164 NeutralElement, Idx);
7168 MO.
setReg(NewVec.getReg(0));
7180 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7182 unsigned MaskNumElts = Mask.size();
7183 unsigned SrcNumElts = SrcTy.getNumElements();
7186 if (MaskNumElts == SrcNumElts)
7189 if (MaskNumElts < SrcNumElts) {
7197 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7198 MI.getOperand(1).getReg(),
7199 MI.getOperand(2).getReg(), NewMask);
7200 MI.eraseFromParent();
7205 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7206 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7215 MOps1[0] =
MI.getOperand(1).getReg();
7216 MOps2[0] =
MI.getOperand(2).getReg();
7218 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7219 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7223 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7225 if (Idx >=
static_cast<int>(SrcNumElts))
7226 Idx += PaddedMaskNumElts - SrcNumElts;
7231 if (MaskNumElts != PaddedMaskNumElts) {
7233 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7236 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7238 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7243 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7246 MI.eraseFromParent();
7252 unsigned int TypeIdx,
LLT MoreTy) {
7253 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7255 unsigned NumElts = DstTy.getNumElements();
7258 if (DstTy.isVector() && Src1Ty.isVector() &&
7259 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7267 if (DstTy != Src1Ty || DstTy != Src2Ty)
7275 for (
unsigned I = 0;
I != NumElts; ++
I) {
7277 if (Idx <
static_cast<int>(NumElts))
7280 NewMask[
I] = Idx - NumElts + WidenNumElts;
7284 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7285 MI.getOperand(1).getReg(),
7286 MI.getOperand(2).getReg(), NewMask);
7287 MI.eraseFromParent();
7296 unsigned SrcParts = Src1Regs.
size();
7297 unsigned DstParts = DstRegs.
size();
7299 unsigned DstIdx = 0;
7301 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7302 DstRegs[DstIdx] = FactorSum;
7307 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7309 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7310 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7312 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7318 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7319 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7320 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7321 unsigned i = RevI - 1;
7323 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7333 if (DstIdx != DstParts - 1) {
7334 MachineInstrBuilder Uaddo =
7335 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7336 FactorSum = Uaddo.
getReg(0);
7337 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7338 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7339 MachineInstrBuilder Uaddo =
7340 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7341 FactorSum = Uaddo.
getReg(0);
7342 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7343 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7347 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7348 for (
unsigned i = 2; i < Factors.
size(); ++i)
7349 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7352 CarrySumPrevDstIdx = CarrySum;
7353 DstRegs[DstIdx] = FactorSum;
7365 LLT DstType = MRI.getType(DstReg);
7367 if (DstType.isVector())
7370 unsigned Opcode =
MI.getOpcode();
7371 unsigned OpO, OpE, OpF;
7373 case TargetOpcode::G_SADDO:
7374 case TargetOpcode::G_SADDE:
7375 case TargetOpcode::G_UADDO:
7376 case TargetOpcode::G_UADDE:
7377 case TargetOpcode::G_ADD:
7378 OpO = TargetOpcode::G_UADDO;
7379 OpE = TargetOpcode::G_UADDE;
7380 OpF = TargetOpcode::G_UADDE;
7381 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7382 OpF = TargetOpcode::G_SADDE;
7384 case TargetOpcode::G_SSUBO:
7385 case TargetOpcode::G_SSUBE:
7386 case TargetOpcode::G_USUBO:
7387 case TargetOpcode::G_USUBE:
7388 case TargetOpcode::G_SUB:
7389 OpO = TargetOpcode::G_USUBO;
7390 OpE = TargetOpcode::G_USUBE;
7391 OpF = TargetOpcode::G_USUBE;
7392 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7393 OpF = TargetOpcode::G_SSUBE;
7400 unsigned NumDefs =
MI.getNumExplicitDefs();
7401 Register Src1 =
MI.getOperand(NumDefs).getReg();
7402 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7405 CarryDst =
MI.getOperand(1).getReg();
7406 if (
MI.getNumOperands() == NumDefs + 3)
7407 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7409 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7410 LLT LeftoverTy, DummyTy;
7412 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7417 int NarrowParts = Src1Regs.
size();
7418 Src1Regs.
append(Src1Left);
7419 Src2Regs.
append(Src2Left);
7422 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7424 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7427 if (i == e - 1 && CarryDst)
7428 CarryOut = CarryDst;
7430 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7433 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7434 {Src1Regs[i], Src2Regs[i]});
7435 }
else if (i == e - 1) {
7436 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7437 {Src1Regs[i], Src2Regs[i], CarryIn});
7439 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7440 {Src1Regs[i], Src2Regs[i], CarryIn});
7446 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7447 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7448 ArrayRef(DstRegs).drop_front(NarrowParts));
7450 MI.eraseFromParent();
7456 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7458 LLT Ty = MRI.getType(DstReg);
7462 unsigned Size = Ty.getSizeInBits();
7464 if (
Size % NarrowSize != 0)
7467 unsigned NumParts =
Size / NarrowSize;
7468 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7469 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7475 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7479 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7480 MI.eraseFromParent();
7490 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7493 LLT SrcTy = MRI.getType(Src);
7504 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7517 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7520 if (SizeOp1 % NarrowSize != 0)
7522 int NumParts = SizeOp1 / NarrowSize;
7525 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7529 uint64_t OpStart =
MI.getOperand(2).getImm();
7530 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7531 for (
int i = 0; i < NumParts; ++i) {
7532 unsigned SrcStart = i * NarrowSize;
7534 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7537 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7545 int64_t ExtractOffset;
7547 if (OpStart < SrcStart) {
7549 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7551 ExtractOffset = OpStart - SrcStart;
7552 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7556 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7558 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7559 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7566 if (MRI.getType(DstReg).isVector())
7567 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7568 else if (DstRegs.
size() > 1)
7569 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7572 MI.eraseFromParent();
7584 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7586 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7589 SrcRegs.
append(LeftoverRegs);
7593 uint64_t OpStart =
MI.getOperand(3).getImm();
7594 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7595 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7596 unsigned DstStart =
I * NarrowSize;
7598 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7606 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7608 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7612 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7620 int64_t ExtractOffset, InsertOffset;
7622 if (OpStart < DstStart) {
7624 ExtractOffset = DstStart - OpStart;
7625 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7627 InsertOffset = OpStart - DstStart;
7630 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7634 if (ExtractOffset != 0 || SegSize != OpSize) {
7636 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7637 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7640 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7641 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7645 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7649 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7652 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7654 MI.eraseFromParent();
7662 LLT DstTy = MRI.getType(DstReg);
7664 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7670 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7671 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7675 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7676 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7679 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7680 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7681 {Src0Regs[I], Src1Regs[I]});
7685 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7688 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7689 DstLeftoverRegs.
push_back(Inst.getReg(0));
7692 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7693 LeftoverTy, DstLeftoverRegs);
7695 MI.eraseFromParent();
7705 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7707 LLT DstTy = MRI.getType(DstReg);
7712 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7713 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7714 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7716 MI.eraseFromParent();
7726 Register CondReg =
MI.getOperand(1).getReg();
7727 LLT CondTy = MRI.getType(CondReg);
7728 if (CondTy.isVector())
7732 LLT DstTy = MRI.getType(DstReg);
7738 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7739 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7743 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7744 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7747 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7749 CondReg, Src1Regs[
I], Src2Regs[
I]);
7753 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7755 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7759 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7760 LeftoverTy, DstLeftoverRegs);
7762 MI.eraseFromParent();
7772 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7775 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7776 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7779 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7781 auto C_0 =
B.buildConstant(NarrowTy, 0);
7783 UnmergeSrc.getReg(1), C_0);
7784 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7785 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7786 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7787 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7788 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7789 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7791 MI.eraseFromParent();
7804 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7807 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7808 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7811 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7813 auto C_0 =
B.buildConstant(NarrowTy, 0);
7815 UnmergeSrc.getReg(0), C_0);
7816 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7817 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7818 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7819 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7820 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7821 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7823 MI.eraseFromParent();
7836 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7839 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7844 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7848 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7849 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7857 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7858 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7861 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7862 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7864 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7866 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7868 MI.eraseFromParent();
7878 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7881 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7882 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7884 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7885 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7886 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7888 MI.eraseFromParent();
7903 LLT ExpTy = MRI.getType(ExpReg);
7908 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7909 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7910 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7911 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7913 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7915 MI.getOperand(2).setReg(Trunc.getReg(0));
7922 unsigned Opc =
MI.getOpcode();
7925 auto QAction = LI.getAction(Q).Action;
7931 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7934 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7938 case TargetOpcode::G_CTLZ: {
7939 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7940 unsigned Len = SrcTy.getScalarSizeInBits();
7942 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7944 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7945 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7948 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7949 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7950 MI.eraseFromParent();
7966 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7967 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7970 Op = MIBOp.getReg(0);
7975 MI.eraseFromParent();
7978 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7981 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7985 case TargetOpcode::G_CTTZ: {
7986 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7988 unsigned Len = SrcTy.getScalarSizeInBits();
7989 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
7992 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
7993 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7996 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7997 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7998 MI.eraseFromParent();
8005 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8006 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8008 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8009 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8010 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8011 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8014 MI.eraseFromParent();
8018 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8019 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8023 case TargetOpcode::G_CTPOP: {
8025 LLT Ty = MRI.getType(SrcReg);
8026 unsigned Size = Ty.getScalarSizeInBits();
8038 auto C_1 =
B.buildConstant(Ty, 1);
8039 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8041 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8042 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8043 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8047 auto C_2 =
B.buildConstant(Ty, 2);
8048 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8050 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8051 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8052 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8053 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8060 auto C_4 =
B.buildConstant(Ty, 4);
8061 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8062 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8064 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8065 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8067 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8070 if (
Size == 16 && !Ty.isVector()) {
8072 auto C_8 =
B.buildConstant(Ty, 8);
8073 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8074 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8075 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8076 MI.eraseFromParent();
8085 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8087 auto IsMulSupported = [
this](
const LLT Ty) {
8088 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8091 if (IsMulSupported(Ty)) {
8092 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8093 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8095 auto ResTmp = B8Count;
8096 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8097 auto ShiftC =
B.buildConstant(Ty, Shift);
8098 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8099 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8101 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8103 MI.eraseFromParent();
8106 case TargetOpcode::G_CTLS: {
8107 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8111 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8112 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8114 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8120 MI.eraseFromParent();
8141 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8142 LLT Ty = MRI.getType(Dst);
8143 LLT ShTy = MRI.getType(Z);
8150 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8151 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8156 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8157 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8161 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8174 MI.eraseFromParent();
8180 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8181 LLT Ty = MRI.getType(Dst);
8182 LLT ShTy = MRI.getType(Z);
8185 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8195 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8196 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8197 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8198 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8199 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8203 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8206 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8209 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8211 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8212 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8213 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8216 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8218 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8220 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8223 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8224 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8229 MI.eraseFromParent();
8240 LLT Ty = MRI.getType(Dst);
8241 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8243 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8244 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8247 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8248 return lowerFunnelShiftAsShifts(
MI);
8252 if (Result == UnableToLegalize)
8253 return lowerFunnelShiftAsShifts(
MI);
8258 auto [Dst, Src] =
MI.getFirst2Regs();
8259 LLT DstTy = MRI.getType(Dst);
8260 LLT SrcTy = MRI.getType(Src);
8264 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8272 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8276 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8280 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8285 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8286 {UnmergeSrc.getReg(0)});
8287 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8288 {UnmergeSrc.getReg(1)});
8291 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8293 MI.eraseFromParent();
8310 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8314 LLT DstTy = MRI.getType(DstReg);
8315 LLT SrcTy = MRI.getType(SrcReg);
8323 SrcTy.getElementCount().divideCoefficientBy(2));
8336 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8348 MI.eraseFromParent();
8357 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8358 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8359 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8360 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8361 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8362 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8363 MI.eraseFromParent();
8368 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8370 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8371 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8376 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8377 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8379 return lowerRotateWithReverseRotate(
MI);
8382 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8383 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8384 bool IsFShLegal =
false;
8385 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8386 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8390 MI.eraseFromParent();
8395 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8398 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8403 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8404 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8405 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8411 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8412 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8414 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8420 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8421 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8423 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8425 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8430 MI.eraseFromParent();
8438 auto [Dst, Src] =
MI.getFirst2Regs();
8443 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8456 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8458 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8463 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8465 MI.eraseFromParent();
8473 auto [Dst, Src] =
MI.getFirst2Regs();
8477 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8488 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8489 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8491 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8498 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8499 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8500 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8502 MI.eraseFromParent();
8513 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8514 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8520 MI.eraseFromParent();
8525 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8528 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8529 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8530 MIRBuilder.buildSelect(Dst, Src, True, False);
8531 MI.eraseFromParent();
8535 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8555 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8562 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8563 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8564 MIRBuilder.buildSelect(Dst, Src, True, False);
8565 MI.eraseFromParent();
8569 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8575 if (DstTy.getScalarSizeInBits() == 32) {
8582 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8583 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8585 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8592 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8593 MI.eraseFromParent();
8601 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8605 if (SrcTy !=
S64 && SrcTy !=
S32)
8607 if (DstTy !=
S32 && DstTy !=
S64)
8634 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8636 MI.eraseFromParent();
8641 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8646 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8653 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8655 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8656 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8658 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8659 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8661 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8663 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8664 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8665 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8668 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8669 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8670 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8672 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8675 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8680 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8681 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8687 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8689 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8690 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8692 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8697 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8698 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8700 MI.eraseFromParent();
8706 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8708 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8709 unsigned SatWidth = DstTy.getScalarSizeInBits();
8713 APInt MinInt, MaxInt;
8736 if (AreExactFloatBounds) {
8738 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8741 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8743 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8752 MI.eraseFromParent();
8757 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8762 MI.eraseFromParent();
8769 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8777 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8787 MI.eraseFromParent();
8793 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8797 MI.eraseFromParent();
8804 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8805 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8806 "Only G_FPEXT and G_FPTRUNC are expected");
8808 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8813 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8815 StoreOpc = TargetOpcode::G_STORE;
8816 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8819 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8820 LoadOpc = TargetOpcode::G_LOAD;
8829 StackTy, StackTyAlign);
8830 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8833 StackTy, StackTyAlign);
8834 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8836 MI.eraseFromParent();
8844 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8845 assert(SrcTy.getScalarType().isBFloat16() &&
8846 "expected a bf16 source for bf16 fpext lowering");
8857 if (DstTy.getScalarType().isFloat32())
8862 MI.eraseFromParent();
8867 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8868 if (SrcTy.getScalarType().isBFloat16() &&
8869 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8881 auto [Dst, Src] =
MI.getFirst2Regs();
8885 if (MRI.getType(Src).isVector())
8889 unsigned Flags =
MI.getFlags();
8892 MI.eraseFromParent();
8896 const unsigned ExpMask = 0x7ff;
8897 const unsigned ExpBiasf64 = 1023;
8898 const unsigned ExpBiasf16 = 15;
8900 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8910 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8917 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8919 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8921 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8925 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8927 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8929 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8930 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8938 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8939 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
8950 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
8961 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
8977 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
8987 MI.eraseFromParent();
8994 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9002 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9028 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9030 MI.eraseFromParent();
9039 LLT OperandTy = MRI.getType(
Op);
9049 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9051 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9052 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9053 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9054 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9055 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9063 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9066 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9068 AbsWide, AbsNarrowAsWide);
9072 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9073 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9075 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9076 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9082 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9088 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9089 MI.eraseFromParent();
9095 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9096 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9099 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9102 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9109 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9110 LLT Ty = MRI.getType(Dst);
9112 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9113 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9114 MI.eraseFromParent();
9119 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9120 LLT Ty = MRI.getType(Src);
9121 auto Flags =
MI.getFlags();
9129 FracToUse = FracPart.getReg(0);
9131 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9135 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9137 FracToUse =
Select.getReg(0);
9140 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9143 MI.eraseFromParent();
9149 case TargetOpcode::G_SMIN:
9151 case TargetOpcode::G_SMAX:
9153 case TargetOpcode::G_UMIN:
9155 case TargetOpcode::G_UMAX:
9163 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9168 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9169 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9171 MI.eraseFromParent();
9180 LLT DstTy = MRI.getType(Dst);
9181 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9191 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9192 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9194 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9197 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9198 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9199 if (TLI.preferSelectsOverBooleanArithmetic(
9202 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9203 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9205 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9206 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9212 unsigned BoolExtOp =
9214 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9215 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9219 MI.eraseFromParent();
9225 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9226 const int Src0Size = Src0Ty.getScalarSizeInBits();
9227 const int Src1Size = Src1Ty.getScalarSizeInBits();
9237 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9238 Src0Ty.getScalarType().isInteger()))
9239 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9241 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9242 Src1Ty.getScalarType().isInteger()))
9243 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9248 auto NotSignBitMask =
MIRBuilder.buildConstant(
9252 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9254 if (Src0Ty == Src1Ty) {
9255 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9256 }
else if (Src0Size > Src1Size) {
9257 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9258 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9259 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9260 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9262 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9263 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9264 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9265 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9271 unsigned Flags =
MI.getFlags();
9276 if (DstTy == DstIntTy)
9277 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9283 MI.eraseFromParent();
9294 switch (
MI.getOpcode()) {
9295 case TargetOpcode::G_FMINNUM:
9296 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9298 case TargetOpcode::G_FMINIMUMNUM:
9299 NewOp = TargetOpcode::G_FMINNUM;
9301 case TargetOpcode::G_FMAXNUM:
9302 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9304 case TargetOpcode::G_FMAXIMUMNUM:
9305 NewOp = TargetOpcode::G_FMAXNUM;
9311 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9312 LLT Ty = MRI.getType(Dst);
9321 if (!VT->isKnownNeverSNaN(Src0))
9322 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9324 if (!VT->isKnownNeverSNaN(Src1))
9325 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9330 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9331 MI.eraseFromParent();
9337 unsigned Opc =
MI.getOpcode();
9338 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9339 LLT Ty = MRI.getType(Dst);
9342 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9344 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9345 unsigned OpcNonIeee =
9346 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9347 bool MinMaxMustRespectOrderedZero =
false;
9351 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9353 MinMaxMustRespectOrderedZero =
true;
9354 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9359 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9364 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9367 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9371 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9373 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9383 const unsigned Flags =
MI.getFlags();
9389 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9391 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9393 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9395 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9397 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9402 MI.eraseFromParent();
9409 LLT Ty = MRI.getType(DstReg);
9410 unsigned Flags =
MI.getFlags();
9415 MI.eraseFromParent();
9421 auto [DstReg,
X] =
MI.getFirst2Regs();
9422 const unsigned Flags =
MI.getFlags();
9423 const LLT Ty = MRI.getType(DstReg);
9435 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9437 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9442 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9443 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9444 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9445 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9447 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9449 MI.eraseFromParent();
9454 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9455 unsigned Flags =
MI.getFlags();
9456 LLT Ty = MRI.getType(DstReg);
9463 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9464 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9467 SrcReg, Zero, Flags);
9469 SrcReg, Trunc, Flags);
9473 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9474 MI.eraseFromParent();
9480 const unsigned NumOps =
MI.getNumOperands();
9481 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9482 unsigned PartSize = Src0Ty.getSizeInBits();
9487 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9488 const unsigned Offset = (
I - 1) * PartSize;
9491 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9494 MRI.createGenericVirtualRegister(WideTy);
9497 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9498 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9499 ResultReg = NextResult;
9502 if (DstTy.isPointer()) {
9503 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9504 DstTy.getAddressSpace())) {
9510 }
else if (WideTy != DstTy) {
9514 MI.eraseFromParent();
9520 const unsigned NumDst =
MI.getNumOperands() - 1;
9521 Register SrcReg =
MI.getOperand(NumDst).getReg();
9522 Register Dst0Reg =
MI.getOperand(0).getReg();
9523 LLT DstTy = MRI.getType(Dst0Reg);
9532 LLT IntTy = MRI.getType(SrcReg);
9537 unsigned Offset = DstSize;
9538 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9540 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9544 MI.eraseFromParent();
9563 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9564 InsertVal =
MI.getOperand(2).getReg();
9566 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9568 LLT VecTy = MRI.getType(SrcVec);
9578 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9579 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9581 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9584 MI.eraseFromParent();
9589 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9600 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9607 int64_t
Offset = IdxVal * EltBytes;
9618 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9621 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9623 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9626 MI.eraseFromParent();
9632 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9633 MI.getFirst3RegLLTs();
9643 for (
int Idx : Mask) {
9645 if (!
Undef.isValid())
9651 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9653 int NumElts = Src0Ty.getNumElements();
9654 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9655 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9656 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9658 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9660 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9665 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9666 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9667 MI.eraseFromParent();
9673 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9674 MI.getFirst4RegLLTs();
9676 if (VecTy.isScalableVector())
9692 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9697 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9700 std::optional<APInt> PassthruSplatVal =
9703 if (PassthruSplatVal.has_value()) {
9705 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9706 }
else if (HasPassthru) {
9707 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9708 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9714 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9718 unsigned NumElmts = VecTy.getNumElements();
9719 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9721 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9724 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9727 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9732 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9734 if (HasPassthru &&
I == NumElmts - 1) {
9737 auto AllLanesSelected =
MIRBuilder.buildICmp(
9739 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9740 {OutPos, EndOfVector});
9744 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9746 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9751 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9753 MI.eraseFromParent();
9770 if (Alignment >
Align(1)) {
9771 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9782 const auto &MF = *
MI.getMF();
9788 Register AllocSize =
MI.getOperand(1).getReg();
9791 LLT PtrTy = MRI.getType(Dst);
9792 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9799 MI.eraseFromParent();
9805 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9810 MI.eraseFromParent();
9816 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9821 MI.eraseFromParent();
9827 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9828 unsigned Offset =
MI.getOperand(2).getImm();
9831 if (SrcTy.isVector()) {
9832 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9833 unsigned DstSize = DstTy.getSizeInBits();
9835 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9836 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9838 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9842 for (
unsigned Idx =
Offset / SrcEltSize;
9843 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9844 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9846 if (SubVectorElts.
size() == 1)
9847 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9849 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9851 MI.eraseFromParent();
9857 if ((SrcTy.isPointer() &&
9858 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9859 (DstTy.isPointer() &&
9860 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9861 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9865 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9866 (SrcTy.isScalar() || SrcTy.isPointer() ||
9867 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9868 LLT SrcIntTy = SrcTy;
9869 if (!SrcTy.isScalar()) {
9871 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9875 if (DstTy.isPointer())
9877 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9883 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9887 if (DstTy.isPointer())
9890 MI.eraseFromParent();
9898 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9899 uint64_t
Offset =
MI.getOperand(3).getImm();
9901 LLT DstTy = MRI.getType(Src);
9902 LLT InsertTy = MRI.getType(InsertSrc);
9905 bool IsNonIntegralInsert =
9915 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9916 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9923 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9925 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9929 for (; Idx <
Offset / EltSize; ++Idx) {
9930 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9935 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9936 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9938 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9942 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
9944 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
9951 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9954 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9955 MI.eraseFromParent();
9964 if (IsNonIntegralDst || IsNonIntegralInsert) {
9965 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9969 LLT IntDstTy = DstTy;
9973 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9978 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9984 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9990 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9991 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9992 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9995 MI.eraseFromParent();
10001 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10002 MI.getFirst4RegLLTs();
10003 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10006 LLT BoolTy = Dst1Ty;
10008 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10017 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10023 auto ResultLowerThanLHS =
10027 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10031 auto LHSLessThanRHS =
10033 auto ResultNegative =
10035 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10039 MI.eraseFromParent();
10045 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10046 const LLT Ty = MRI.getType(Res);
10049 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10050 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10051 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10055 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10056 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10059 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10062 MI.eraseFromParent();
10067 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10068 const LLT Ty = MRI.getType(Res);
10071 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10072 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10073 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10077 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10078 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10080 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10083 MI.eraseFromParent();
10089 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10090 LLT Ty = MRI.getType(Res);
10094 switch (
MI.getOpcode()) {
10097 case TargetOpcode::G_UADDSAT:
10100 BaseOp = TargetOpcode::G_ADD;
10102 case TargetOpcode::G_SADDSAT:
10105 BaseOp = TargetOpcode::G_ADD;
10107 case TargetOpcode::G_USUBSAT:
10110 BaseOp = TargetOpcode::G_SUB;
10112 case TargetOpcode::G_SSUBSAT:
10115 BaseOp = TargetOpcode::G_SUB;
10130 uint64_t NumBits = Ty.getScalarSizeInBits();
10137 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10141 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10149 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10154 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10155 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10158 MI.eraseFromParent();
10164 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10165 LLT Ty = MRI.getType(Res);
10169 unsigned OverflowOp;
10170 switch (
MI.getOpcode()) {
10173 case TargetOpcode::G_UADDSAT:
10176 OverflowOp = TargetOpcode::G_UADDO;
10178 case TargetOpcode::G_SADDSAT:
10181 OverflowOp = TargetOpcode::G_SADDO;
10183 case TargetOpcode::G_USUBSAT:
10186 OverflowOp = TargetOpcode::G_USUBO;
10188 case TargetOpcode::G_SSUBSAT:
10191 OverflowOp = TargetOpcode::G_SSUBO;
10196 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10197 Register Tmp = OverflowRes.getReg(0);
10198 Register Ov = OverflowRes.getReg(1);
10207 uint64_t NumBits = Ty.getScalarSizeInBits();
10208 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10209 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10212 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10220 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10222 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10224 MI.eraseFromParent();
10230 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10231 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10232 "Expected shlsat opcode!");
10233 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10234 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10235 LLT Ty = MRI.getType(Res);
10239 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10240 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10249 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10254 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10256 MI.eraseFromParent();
10262 unsigned Opc =
MI.getOpcode();
10263 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10264 unsigned DstSize = DstTy.getScalarSizeInBits();
10265 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10267 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10270 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10273 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10274 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10277 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10278 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10281 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10283 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10289 MI.eraseFromParent();
10294 auto [Dst, Src] =
MI.getFirst2Regs();
10295 const LLT Ty = MRI.getType(Src);
10296 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10297 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10300 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10301 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10302 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10303 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10306 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10309 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10310 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10312 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10313 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10314 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10316 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10317 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10318 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10320 Res.getInstr()->getOperand(0).setReg(Dst);
10322 MI.eraseFromParent();
10329 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10332 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10333 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10334 return B.buildOr(Dst,
LHS,
RHS);
10339 auto [Dst, Src] =
MI.getFirst2Regs();
10340 const LLT SrcTy = MRI.getType(Src);
10341 unsigned Size = SrcTy.getScalarSizeInBits();
10342 unsigned VSize = SrcTy.getSizeInBits();
10345 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10346 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10347 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10348 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10353 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10354 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10355 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10359 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10382 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10386 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10389 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10393 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10397 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10402 MI.eraseFromParent();
10410 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10411 int NameOpIdx = IsRead ? 1 : 0;
10412 int ValRegIndex = IsRead ? 0 : 1;
10414 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10415 const LLT Ty = MRI.getType(ValReg);
10417 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10424 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10425 Fn,
MI.getDebugLoc()));
10429 MI.eraseFromParent();
10438 MI.eraseFromParent();
10444 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10445 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10446 Register Result =
MI.getOperand(0).getReg();
10447 LLT OrigTy = MRI.getType(Result);
10451 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10452 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10454 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10456 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10457 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10460 MI.eraseFromParent();
10466 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10471 MI.eraseFromParent();
10476 MI.eraseFromParent();
10483 unsigned BitSize = SrcTy.getScalarSizeInBits();
10487 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10494 APInt ExpMask = Inf;
10496 APInt QNaNBitMask =
10500 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10501 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10502 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10503 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10504 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10506 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10510 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10512 LLT DstTyCopy = DstTy;
10514 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10542 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10545 Mask &= ~PartialCheck;
10554 else if (PartialCheck ==
fcZero)
10566 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10567 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10568 auto SubnormalRes =
10570 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10572 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10573 appendToRes(SubnormalRes);
10580 else if (PartialCheck ==
fcInf)
10585 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10592 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10593 if (PartialCheck ==
fcNan) {
10597 }
else if (PartialCheck ==
fcQNan) {
10607 Abs, InfWithQnanBitC);
10608 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10615 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10617 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10618 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10621 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10623 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10626 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10627 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10629 appendToRes(NormalRes);
10633 MI.eraseFromParent();
10639 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10640 MI.getFirst4RegLLTs();
10649 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10650 Op1Ty = MRI.getType(Op1Reg);
10651 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10652 Op2Ty = MRI.getType(Op2Reg);
10656 if (MaskTy.isScalar()) {
10664 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10667 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10669 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10671 if (DstTy.isVector()) {
10673 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10674 MaskReg = ShufSplat.getReg(0);
10678 }
else if (!DstTy.isVector()) {
10683 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10687 if (!Op1Ty.getScalarType().isAnyScalar() &&
10688 !Op1Ty.getScalarType().isInteger())
10689 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10691 if (!Op2Ty.getScalarType().isAnyScalar() &&
10692 !Op2Ty.getScalarType().isInteger()) {
10694 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10695 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10698 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10699 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10700 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10705 if (DstTy == Op1TyInt)
10708 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10712 MI.eraseFromParent();
10718 unsigned Opcode =
MI.getOpcode();
10721 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10722 : TargetOpcode::G_UDIV,
10723 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10725 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10726 : TargetOpcode::G_UREM,
10727 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10728 MI.eraseFromParent();
10738 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10742 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10745 MI.eraseFromParent();
10755 Register SrcReg =
MI.getOperand(1).getReg();
10756 LLT Ty = MRI.getType(SrcReg);
10757 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10760 MI.eraseFromParent();
10766 Register SrcReg =
MI.getOperand(1).getReg();
10767 Register DestReg =
MI.getOperand(0).getReg();
10769 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10770 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10773 MI.eraseFromParent();
10779 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10780 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10781 "Expected G_ABDS or G_ABDU instruction");
10783 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10784 LLT Ty = MRI.getType(LHS);
10794 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10796 MI.eraseFromParent();
10802 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10803 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10804 "Expected G_ABDS or G_ABDU instruction");
10806 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10807 LLT Ty = MRI.getType(LHS);
10812 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10813 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10814 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10816 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10817 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10819 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10821 MI.eraseFromParent();
10826 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10831 if (!(SrcTy.getScalarType().isAnyScalar() ||
10832 SrcTy.getScalarType().isInteger())) {
10834 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10835 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10838 if (MRI.getType(DstReg) != TyInt) {
10842 .buildAnd(TyInt, CastedSrc,
10845 DstTy.getScalarSizeInBits())))
10857 MI.eraseFromParent();
10863 Register SrcReg =
MI.getOperand(1).getReg();
10864 LLT SrcTy = MRI.getType(SrcReg);
10865 LLT DstTy = MRI.getType(SrcReg);
10868 if (SrcTy.isScalar()) {
10873 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10884 Register ListPtr =
MI.getOperand(1).getReg();
10885 LLT PtrTy = MRI.getType(ListPtr);
10892 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10894 const Align A(
MI.getOperand(2).getImm());
10896 if (
A > TLI.getMinStackArgumentAlignment()) {
10898 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10899 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10900 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10901 VAList = AndDst.getReg(0);
10908 LLT LLTTy = MRI.getType(Dst);
10911 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10912 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10917 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10919 Align EltAlignment =
DL.getABITypeAlign(Ty);
10922 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10924 MI.eraseFromParent();
10929 unsigned OpCode =
MI.getOpcode();
10930 assert((OpCode == TargetOpcode::G_SMULFIX ||
10931 OpCode == TargetOpcode::G_UMULFIX ||
10932 OpCode == TargetOpcode::G_SMULFIXSAT ||
10933 OpCode == TargetOpcode::G_UMULFIXSAT) &&
10934 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
10935 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10936 LLT Ty = MRI.getType(Dst);
10937 unsigned Scale =
MI.getOperand(3).getImm();
10939 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
10940 OpCode == TargetOpcode::G_UMULFIXSAT);
10941 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
10942 OpCode == TargetOpcode::G_SMULFIXSAT);
10944 if (!Saturating && Scale == 0) {
10946 MI.eraseFromParent();
10952 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
10975 MI.eraseFromParent();
10982 unsigned NumBits = Ty.getScalarSizeInBits();
10984 if (!Ty.isVector() && ValVRegAndVal) {
10985 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10993 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11016 auto &MF = *
MI.getParent()->getParent();
11021 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11022 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11025 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11026 const auto &DstMMO = **
MI.memoperands_begin();
11028 if (DstAlignCanChange) {
11031 Align NewAlign =
DL.getABITypeAlign(IRTy);
11032 if (NewAlign > Alignment) {
11041 MachineIRBuilder MIB(
MI);
11043 LLT LargestTy = MemOps[0];
11044 for (
unsigned i = 1; i < MemOps.
size(); i++)
11046 LargestTy = MemOps[i];
11058 LLT PtrTy = MRI.getType(Dst);
11059 unsigned DstOff = 0;
11060 unsigned Size = KnownLen;
11061 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11062 LLT Ty = MemOps[
I];
11065 if (TySize >
Size) {
11069 DstOff -= TySize -
Size;
11079 TLI.isTruncateFree(LargestVT, VT))
11080 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11093 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11096 MIB.buildStore(
Value, Ptr, *StoreMMO);
11101 MI.eraseFromParent();
11109 auto &MF = *
MI.getParent()->getParent();
11113 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11114 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11117 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11123 const auto &DstMMO = **
MI.memoperands_begin();
11124 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11126 if (DstAlignCanChange) {
11129 Align NewAlign =
DL.getABITypeAlign(IRTy);
11134 if (!
TRI->hasStackRealignment(MF))
11135 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11136 NewAlign = std::min(NewAlign, *StackAlign);
11138 if (NewAlign > Alignment) {
11147 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11149 MachineIRBuilder MIB(
MI);
11155 unsigned CurrOffset = 0;
11156 unsigned Size = KnownLen;
11157 for (
auto CopyTy : MemOps) {
11158 TypeSize TySize = CopyTy.getSizeInBytes();
11162 if (TySize >
Size) {
11163 unsigned Overlap = TySize -
Size;
11164 assert(Overlap < CurrOffset &&
11165 "overlapping memcpy load/store spans the whole region or more");
11166 CurrOffset -= Overlap;
11176 if (CurrOffset != 0) {
11177 LLT SrcTy = MRI.getType(Src);
11181 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11183 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11187 if (CurrOffset != 0) {
11188 LLT DstTy = MRI.getType(Dst);
11189 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11191 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11192 CurrOffset += TySize;
11196 MI.eraseFromParent();
11204 auto &MF = *
MI.getParent()->getParent();
11208 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11209 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11212 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11213 const auto &DstMMO = **
MI.memoperands_begin();
11214 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11216 if (DstAlignCanChange) {
11219 Align NewAlign =
DL.getABITypeAlign(IRTy);
11224 if (!
TRI->hasStackRealignment(MF))
11225 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11226 NewAlign = std::min(NewAlign, *StackAlign);
11228 if (NewAlign > Alignment) {
11237 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11239 MachineIRBuilder MIB(
MI);
11243 unsigned CurrOffset = 0;
11244 unsigned Size = KnownLen;
11245 SmallVector<Register, 16> LoadVals;
11246 for (
auto CopyTy : MemOps) {
11247 TypeSize TySize = CopyTy.getSizeInBytes();
11251 if (TySize >
Size) {
11252 unsigned Overlap = TySize -
Size;
11253 assert(Overlap < CurrOffset &&
11254 "overlapping memmove load spans the whole region or more");
11255 CurrOffset -= Overlap;
11263 if (CurrOffset != 0) {
11264 LLT SrcTy = MRI.getType(Src);
11267 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11269 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11270 CurrOffset += TySize;
11276 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11277 LLT CopyTy = MemOps[
I];
11282 if (TySize >
Size) {
11283 unsigned Overlap = TySize -
Size;
11284 assert(Overlap < CurrOffset &&
11285 "overlapping memmove store spans the whole region or more");
11286 CurrOffset -= Overlap;
11293 if (CurrOffset != 0) {
11294 LLT DstTy = MRI.getType(Dst);
11297 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11299 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11300 CurrOffset += TySize;
11303 MI.eraseFromParent();
11310 const unsigned Opc =
MI.getOpcode();
11311 assert((
Opc == TargetOpcode::G_MEMCPY ||
11312 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11313 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11314 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11315 "Expected memcpy like instruction");
11317 if (KnownLen == 0) {
11318 MI.eraseFromParent();
11322 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11323 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11326 if (
Opc == TargetOpcode::G_MEMMOVE)
11327 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11329 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11330 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11340 bool DstAlignCanChange;
11341 std::vector<LLT> MemOps;
11343 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.