43#define DEBUG_TYPE "legalizer"
56static std::pair<int, int>
62 unsigned NumParts =
Size / NarrowSize;
63 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
66 if (LeftoverSize == 0)
71 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
127 auto Step = LI.getAction(
MI, MRI);
128 switch (Step.Action) {
143 return bitcast(
MI, Step.TypeIdx, Step.NewType);
146 return lower(
MI, Step.TypeIdx, Step.NewType);
155 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
163void LegalizerHelper::insertParts(
Register DstReg,
185 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
187 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
188 return mergeMixedSubvectors(DstReg, AllRegs);
194 extractGCDType(GCDRegs, GCDTy, PartReg);
195 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
196 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
201 LLT Ty = MRI.getType(
Reg);
209void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
212 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
213 appendVectorElts(AllElts, PartRegs[i]);
216 if (!MRI.getType(Leftover).isVector())
219 appendVectorElts(AllElts, Leftover);
221 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
227 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
229 const int StartIdx = Regs.
size();
230 const int NumResults =
MI.getNumOperands() - 1;
232 for (
int I = 0;
I != NumResults; ++
I)
233 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
238 LLT SrcTy = MRI.getType(SrcReg);
239 if (SrcTy == GCDTy) {
245 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
252 LLT SrcTy = MRI.getType(SrcReg);
254 extractGCDType(Parts, GCDTy, SrcReg);
258LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
260 unsigned PadStrategy) {
265 int NumOrigSrc = VRegs.
size();
271 if (NumOrigSrc < NumParts * NumSubParts) {
272 if (PadStrategy == TargetOpcode::G_ZEXT)
273 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
274 else if (PadStrategy == TargetOpcode::G_ANYEXT)
275 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
277 assert(PadStrategy == TargetOpcode::G_SEXT);
282 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
298 for (
int I = 0;
I != NumParts; ++
I) {
299 bool AllMergePartsArePadding =
true;
302 for (
int J = 0; J != NumSubParts; ++J) {
303 int Idx =
I * NumSubParts + J;
304 if (Idx >= NumOrigSrc) {
305 SubMerge[J] = PadReg;
309 SubMerge[J] = VRegs[Idx];
312 AllMergePartsArePadding =
false;
318 if (AllMergePartsArePadding && !AllPadReg) {
319 if (PadStrategy == TargetOpcode::G_ANYEXT)
320 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
321 else if (PadStrategy == TargetOpcode::G_ZEXT)
322 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
331 Remerge[
I] = AllPadReg;
335 if (NumSubParts == 1)
336 Remerge[
I] = SubMerge[0];
338 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
341 if (AllMergePartsArePadding && !AllPadReg)
342 AllPadReg = Remerge[
I];
345 VRegs = std::move(Remerge);
349void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
351 LLT DstTy = MRI.getType(DstReg);
356 if (DstTy == LCMTy) {
357 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
361 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
370 UnmergeDefs[0] = DstReg;
371 for (
unsigned I = 1;
I != NumDefs; ++
I)
372 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
375 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
383#define RTLIBCASE_INT(LibcallPrefix) \
387 return RTLIB::LibcallPrefix##32; \
389 return RTLIB::LibcallPrefix##64; \
391 return RTLIB::LibcallPrefix##128; \
393 llvm_unreachable("unexpected size"); \
397#define RTLIBCASE(LibcallPrefix) \
401 return RTLIB::LibcallPrefix##32; \
403 return RTLIB::LibcallPrefix##64; \
405 return RTLIB::LibcallPrefix##80; \
407 return RTLIB::LibcallPrefix##128; \
409 llvm_unreachable("unexpected size"); \
414 case TargetOpcode::G_LROUND:
416 case TargetOpcode::G_LLROUND:
418 case TargetOpcode::G_MUL:
420 case TargetOpcode::G_SDIV:
422 case TargetOpcode::G_UDIV:
424 case TargetOpcode::G_SREM:
426 case TargetOpcode::G_UREM:
428 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
430 case TargetOpcode::G_FADD:
432 case TargetOpcode::G_FSUB:
434 case TargetOpcode::G_FMUL:
436 case TargetOpcode::G_FDIV:
438 case TargetOpcode::G_FEXP:
440 case TargetOpcode::G_FEXP2:
442 case TargetOpcode::G_FEXP10:
444 case TargetOpcode::G_FREM:
446 case TargetOpcode::G_FPOW:
448 case TargetOpcode::G_FPOWI:
450 case TargetOpcode::G_FMA:
452 case TargetOpcode::G_FSIN:
454 case TargetOpcode::G_FCOS:
456 case TargetOpcode::G_FTAN:
458 case TargetOpcode::G_FASIN:
460 case TargetOpcode::G_FACOS:
462 case TargetOpcode::G_FATAN:
464 case TargetOpcode::G_FATAN2:
466 case TargetOpcode::G_FSINH:
468 case TargetOpcode::G_FCOSH:
470 case TargetOpcode::G_FTANH:
472 case TargetOpcode::G_FSINCOS:
474 case TargetOpcode::G_FMODF:
476 case TargetOpcode::G_FLOG10:
478 case TargetOpcode::G_FLOG:
480 case TargetOpcode::G_FLOG2:
482 case TargetOpcode::G_FLDEXP:
484 case TargetOpcode::G_FCEIL:
486 case TargetOpcode::G_FFLOOR:
488 case TargetOpcode::G_FMINNUM:
490 case TargetOpcode::G_FMAXNUM:
492 case TargetOpcode::G_FMINIMUMNUM:
494 case TargetOpcode::G_FMAXIMUMNUM:
496 case TargetOpcode::G_FSQRT:
498 case TargetOpcode::G_FRINT:
500 case TargetOpcode::G_FNEARBYINT:
502 case TargetOpcode::G_INTRINSIC_TRUNC:
504 case TargetOpcode::G_INTRINSIC_ROUND:
506 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
508 case TargetOpcode::G_INTRINSIC_LRINT:
510 case TargetOpcode::G_INTRINSIC_LLRINT:
530 AttributeList CallerAttrs =
F.getAttributes();
531 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
532 .removeAttribute(Attribute::NoAlias)
533 .removeAttribute(Attribute::NonNull)
538 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
539 CallerAttrs.hasRetAttr(Attribute::SExt))
550 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
557 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
565 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
568 if (Ret->getNumImplicitOperands() != 1)
571 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
595 Info.OrigRet = Result;
598 (Result.Ty->isVoidTy() ||
604 if (!CLI.lowerCall(MIRBuilder, Info))
607 if (
MI && Info.LoweredTailCall) {
608 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
618 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
619 "Expected instr following MI to be return or debug inst?");
622 Next->eraseFromParent();
623 }
while (
MI->getNextNode());
637 const char *Name = TLI.getLibcallName(
Libcall);
641 return createLibcall(MIRBuilder, Name, Result, Args, CC, LocObserver,
MI);
653 Args.push_back({MO.getReg(), OpType, 0});
655 {
MI.getOperand(0).getReg(), OpType, 0}, Args,
662 MachineFunction &MF = *
MI.getMF();
668 LLT DstTy = MRI.getType(DstSin);
673 unsigned AddrSpace =
DL.getAllocaAddrSpace();
674 MachinePointerInfo PtrInfo;
692 if (LibcallResult != LegalizeResult::Legalized)
700 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
701 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
702 MI.eraseFromParent();
717 LLT DstTy = MRI.getType(DstFrac);
722 unsigned AddrSpace =
DL.getAllocaAddrSpace();
723 MachinePointerInfo PtrInfo;
732 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
735 if (LibcallResult != LegalizeResult::Legalized)
741 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
742 MI.eraseFromParent();
754 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
758 LLT OpLLT =
MRI.getType(Reg);
759 Type *OpTy =
nullptr;
764 Args.push_back({Reg, OpTy, 0});
769 RTLIB::Libcall RTLibcall;
770 unsigned Opc =
MI.getOpcode();
773 case TargetOpcode::G_BZERO:
774 RTLibcall = RTLIB::BZERO;
775 Name = TLI.getLibcallName(RTLibcall);
777 case TargetOpcode::G_MEMCPY:
778 RTLibcall = RTLIB::MEMCPY;
779 Name = TLI.getLibcallImplName(TLI.getMemcpyImpl()).data();
780 Args[0].Flags[0].setReturned();
782 case TargetOpcode::G_MEMMOVE:
783 RTLibcall = RTLIB::MEMMOVE;
784 Name = TLI.getLibcallName(RTLibcall);
785 Args[0].Flags[0].setReturned();
787 case TargetOpcode::G_MEMSET:
788 RTLibcall = RTLIB::MEMSET;
789 Name = TLI.getLibcallName(RTLibcall);
790 Args[0].Flags[0].setReturned();
804 Info.
CallConv = TLI.getLibcallCallingConv(RTLibcall);
808 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
812 if (!CLI.lowerCall(MIRBuilder, Info))
815 if (Info.LoweredTailCall) {
816 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
826 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
827 "Expected instr following MI to be return or debug inst?");
830 Next->eraseFromParent();
831 }
while (
MI.getNextNode());
841 unsigned Opc =
MI.getOpcode();
843 auto &MMO = AtomicMI.getMMO();
844 auto Ordering = MMO.getMergedOrdering();
845 LLT MemType = MMO.getMemoryType();
848 return RTLIB::UNKNOWN_LIBCALL;
850#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
852 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
854 case TargetOpcode::G_ATOMIC_CMPXCHG:
855 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
856 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
857 return getOutlineAtomicHelper(LC, Ordering, MemSize);
859 case TargetOpcode::G_ATOMICRMW_XCHG: {
860 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
861 return getOutlineAtomicHelper(LC, Ordering, MemSize);
863 case TargetOpcode::G_ATOMICRMW_ADD:
864 case TargetOpcode::G_ATOMICRMW_SUB: {
865 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
866 return getOutlineAtomicHelper(LC, Ordering, MemSize);
868 case TargetOpcode::G_ATOMICRMW_AND: {
869 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
870 return getOutlineAtomicHelper(LC, Ordering, MemSize);
872 case TargetOpcode::G_ATOMICRMW_OR: {
873 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
874 return getOutlineAtomicHelper(LC, Ordering, MemSize);
876 case TargetOpcode::G_ATOMICRMW_XOR: {
877 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
878 return getOutlineAtomicHelper(LC, Ordering, MemSize);
881 return RTLIB::UNKNOWN_LIBCALL;
894 unsigned Opc =
MI.getOpcode();
896 case TargetOpcode::G_ATOMIC_CMPXCHG:
897 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
900 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
901 MI.getFirst4RegLLTs();
904 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
905 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
906 NewLLT) =
MI.getFirst5RegLLTs();
916 case TargetOpcode::G_ATOMICRMW_XCHG:
917 case TargetOpcode::G_ATOMICRMW_ADD:
918 case TargetOpcode::G_ATOMICRMW_SUB:
919 case TargetOpcode::G_ATOMICRMW_AND:
920 case TargetOpcode::G_ATOMICRMW_OR:
921 case TargetOpcode::G_ATOMICRMW_XOR: {
922 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
925 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
929 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
944 const char *Name = TLI.getLibcallName(RTLibcall);
954 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
959 if (!CLI.lowerCall(MIRBuilder,
Info))
971 case TargetOpcode::G_FPEXT:
973 case TargetOpcode::G_FPTRUNC:
975 case TargetOpcode::G_FPTOSI:
977 case TargetOpcode::G_FPTOUI:
979 case TargetOpcode::G_SITOFP:
981 case TargetOpcode::G_UITOFP:
992 if (FromType->isIntegerTy()) {
994 Arg.
Flags[0].setSExt();
996 Arg.
Flags[0].setZExt();
1001 {
MI.getOperand(0).getReg(), ToType, 0}, Arg, LocObserver,
1005static RTLIB::Libcall
1007 RTLIB::Libcall RTLibcall;
1008 switch (
MI.getOpcode()) {
1009 case TargetOpcode::G_GET_FPENV:
1010 RTLibcall = RTLIB::FEGETENV;
1012 case TargetOpcode::G_SET_FPENV:
1013 case TargetOpcode::G_RESET_FPENV:
1014 RTLibcall = RTLIB::FESETENV;
1016 case TargetOpcode::G_GET_FPMODE:
1017 RTLibcall = RTLIB::FEGETMODE;
1019 case TargetOpcode::G_SET_FPMODE:
1020 case TargetOpcode::G_RESET_FPMODE:
1021 RTLibcall = RTLIB::FESETMODE;
1054 LLT StateTy = MRI.getType(Dst);
1057 MachinePointerInfo TempPtrInfo;
1061 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1067 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1068 LocObserver,
nullptr);
1075 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1094 LLT StateTy = MRI.getType(Src);
1097 MachinePointerInfo TempPtrInfo;
1106 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1111 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1112 LocObserver,
nullptr);
1118static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1120#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1124 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1126 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1128 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1130 llvm_unreachable("unexpected size"); \
1162 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1165 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1172 LLT DstTy = MRI.getType(DstReg);
1173 const auto Cond =
Cmp->getCond();
1178 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1183 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1187 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1194 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1200 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1202 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1215 const auto [OeqLibcall, OeqPred] =
1217 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1219 const auto [UnoLibcall, UnoPred] =
1221 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1236 const auto [OeqLibcall, OeqPred] =
1241 const auto [UnoLibcall, UnoPred] =
1246 if (NotOeq && NotUno)
1265 const auto [InversedLibcall, InversedPred] =
1267 if (!BuildLibcall(InversedLibcall,
1293 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1295 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1298 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1304 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}),
1310 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1312 switch (
MI.getOpcode()) {
1315 case TargetOpcode::G_MUL:
1316 case TargetOpcode::G_SDIV:
1317 case TargetOpcode::G_UDIV:
1318 case TargetOpcode::G_SREM:
1319 case TargetOpcode::G_UREM:
1320 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1321 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1329 case TargetOpcode::G_FADD:
1330 case TargetOpcode::G_FSUB:
1331 case TargetOpcode::G_FMUL:
1332 case TargetOpcode::G_FDIV:
1333 case TargetOpcode::G_FMA:
1334 case TargetOpcode::G_FPOW:
1335 case TargetOpcode::G_FREM:
1336 case TargetOpcode::G_FCOS:
1337 case TargetOpcode::G_FSIN:
1338 case TargetOpcode::G_FTAN:
1339 case TargetOpcode::G_FACOS:
1340 case TargetOpcode::G_FASIN:
1341 case TargetOpcode::G_FATAN:
1342 case TargetOpcode::G_FATAN2:
1343 case TargetOpcode::G_FCOSH:
1344 case TargetOpcode::G_FSINH:
1345 case TargetOpcode::G_FTANH:
1346 case TargetOpcode::G_FLOG10:
1347 case TargetOpcode::G_FLOG:
1348 case TargetOpcode::G_FLOG2:
1349 case TargetOpcode::G_FEXP:
1350 case TargetOpcode::G_FEXP2:
1351 case TargetOpcode::G_FEXP10:
1352 case TargetOpcode::G_FCEIL:
1353 case TargetOpcode::G_FFLOOR:
1354 case TargetOpcode::G_FMINNUM:
1355 case TargetOpcode::G_FMAXNUM:
1356 case TargetOpcode::G_FMINIMUMNUM:
1357 case TargetOpcode::G_FMAXIMUMNUM:
1358 case TargetOpcode::G_FSQRT:
1359 case TargetOpcode::G_FRINT:
1360 case TargetOpcode::G_FNEARBYINT:
1361 case TargetOpcode::G_INTRINSIC_TRUNC:
1362 case TargetOpcode::G_INTRINSIC_ROUND:
1363 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1364 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1368 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1376 case TargetOpcode::G_FSINCOS: {
1377 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1381 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1386 case TargetOpcode::G_FMODF: {
1387 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1391 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1396 case TargetOpcode::G_LROUND:
1397 case TargetOpcode::G_LLROUND:
1398 case TargetOpcode::G_INTRINSIC_LRINT:
1399 case TargetOpcode::G_INTRINSIC_LLRINT: {
1400 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1404 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1406 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1412 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1415 MI.eraseFromParent();
1418 case TargetOpcode::G_FPOWI:
1419 case TargetOpcode::G_FLDEXP: {
1420 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1424 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1426 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1431 {
MI.getOperand(1).getReg(), HLTy, 0},
1432 {
MI.getOperand(2).getReg(), ITy, 1}};
1433 Args[1].Flags[0].setSExt();
1436 Args, LocObserver, &
MI);
1441 case TargetOpcode::G_FPEXT:
1442 case TargetOpcode::G_FPTRUNC: {
1445 if (!FromTy || !ToTy)
1453 case TargetOpcode::G_FCMP: {
1457 MI.eraseFromParent();
1460 case TargetOpcode::G_FPTOSI:
1461 case TargetOpcode::G_FPTOUI: {
1465 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1466 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1474 case TargetOpcode::G_SITOFP:
1475 case TargetOpcode::G_UITOFP: {
1476 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1479 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1481 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1484 LocObserver, TLI, IsSigned);
1489 case TargetOpcode::G_ATOMICRMW_XCHG:
1490 case TargetOpcode::G_ATOMICRMW_ADD:
1491 case TargetOpcode::G_ATOMICRMW_SUB:
1492 case TargetOpcode::G_ATOMICRMW_AND:
1493 case TargetOpcode::G_ATOMICRMW_OR:
1494 case TargetOpcode::G_ATOMICRMW_XOR:
1495 case TargetOpcode::G_ATOMIC_CMPXCHG:
1496 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1502 case TargetOpcode::G_BZERO:
1503 case TargetOpcode::G_MEMCPY:
1504 case TargetOpcode::G_MEMMOVE:
1505 case TargetOpcode::G_MEMSET: {
1510 MI.eraseFromParent();
1513 case TargetOpcode::G_GET_FPENV:
1514 case TargetOpcode::G_GET_FPMODE: {
1520 case TargetOpcode::G_SET_FPENV:
1521 case TargetOpcode::G_SET_FPMODE: {
1527 case TargetOpcode::G_RESET_FPENV:
1528 case TargetOpcode::G_RESET_FPMODE: {
1537 MI.eraseFromParent();
1544 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1547 switch (
MI.getOpcode()) {
1550 case TargetOpcode::G_IMPLICIT_DEF: {
1552 LLT DstTy = MRI.getType(DstReg);
1560 if (SizeOp0 % NarrowSize != 0) {
1561 LLT ImplicitTy = NarrowTy;
1568 MI.eraseFromParent();
1572 int NumParts = SizeOp0 / NarrowSize;
1575 for (
int i = 0; i < NumParts; ++i)
1579 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1581 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1582 MI.eraseFromParent();
1585 case TargetOpcode::G_CONSTANT: {
1586 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1587 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1588 unsigned TotalSize = Ty.getSizeInBits();
1590 int NumParts = TotalSize / NarrowSize;
1593 for (
int I = 0;
I != NumParts; ++
I) {
1594 unsigned Offset =
I * NarrowSize;
1601 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1603 if (LeftoverBits != 0) {
1607 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1611 insertParts(
MI.getOperand(0).getReg(),
1612 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1614 MI.eraseFromParent();
1617 case TargetOpcode::G_SEXT:
1618 case TargetOpcode::G_ZEXT:
1619 case TargetOpcode::G_ANYEXT:
1621 case TargetOpcode::G_TRUNC: {
1625 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1627 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1631 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1632 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1633 MI.eraseFromParent();
1636 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1637 case TargetOpcode::G_FREEZE: {
1641 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1646 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1648 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1650 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1654 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1655 MI.eraseFromParent();
1658 case TargetOpcode::G_ADD:
1659 case TargetOpcode::G_SUB:
1660 case TargetOpcode::G_SADDO:
1661 case TargetOpcode::G_SSUBO:
1662 case TargetOpcode::G_SADDE:
1663 case TargetOpcode::G_SSUBE:
1664 case TargetOpcode::G_UADDO:
1665 case TargetOpcode::G_USUBO:
1666 case TargetOpcode::G_UADDE:
1667 case TargetOpcode::G_USUBE:
1669 case TargetOpcode::G_MUL:
1670 case TargetOpcode::G_UMULH:
1672 case TargetOpcode::G_EXTRACT:
1674 case TargetOpcode::G_INSERT:
1676 case TargetOpcode::G_LOAD: {
1678 Register DstReg = LoadMI.getDstReg();
1679 LLT DstTy = MRI.getType(DstReg);
1683 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1684 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1685 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1687 LoadMI.eraseFromParent();
1693 case TargetOpcode::G_ZEXTLOAD:
1694 case TargetOpcode::G_SEXTLOAD: {
1696 Register DstReg = LoadMI.getDstReg();
1697 Register PtrReg = LoadMI.getPointerReg();
1699 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1700 auto &MMO = LoadMI.getMMO();
1703 if (MemSize == NarrowSize) {
1705 }
else if (MemSize < NarrowSize) {
1706 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1707 }
else if (MemSize > NarrowSize) {
1717 LoadMI.eraseFromParent();
1720 case TargetOpcode::G_STORE: {
1723 Register SrcReg = StoreMI.getValueReg();
1724 LLT SrcTy = MRI.getType(SrcReg);
1725 if (SrcTy.isVector())
1728 int NumParts = SizeOp0 / NarrowSize;
1730 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1731 if (SrcTy.isVector() && LeftoverBits != 0)
1734 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1735 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1737 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1738 StoreMI.eraseFromParent();
1744 case TargetOpcode::G_SELECT:
1746 case TargetOpcode::G_AND:
1747 case TargetOpcode::G_OR:
1748 case TargetOpcode::G_XOR: {
1760 case TargetOpcode::G_SHL:
1761 case TargetOpcode::G_LSHR:
1762 case TargetOpcode::G_ASHR:
1764 case TargetOpcode::G_CTLZ:
1765 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1766 case TargetOpcode::G_CTTZ:
1767 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1768 case TargetOpcode::G_CTPOP:
1770 switch (
MI.getOpcode()) {
1771 case TargetOpcode::G_CTLZ:
1772 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1774 case TargetOpcode::G_CTTZ:
1775 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1777 case TargetOpcode::G_CTPOP:
1787 case TargetOpcode::G_INTTOPTR:
1795 case TargetOpcode::G_PTRTOINT:
1803 case TargetOpcode::G_PHI: {
1806 if (SizeOp0 % NarrowSize != 0)
1809 unsigned NumParts = SizeOp0 / NarrowSize;
1813 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1821 for (
unsigned i = 0; i < NumParts; ++i) {
1822 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1824 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1825 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1826 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1829 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1831 MI.eraseFromParent();
1834 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1835 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1839 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1845 case TargetOpcode::G_ICMP: {
1847 LLT SrcTy = MRI.getType(LHS);
1853 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1859 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1860 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1866 LLT ResTy = MRI.getType(Dst);
1871 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1873 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1874 auto LHS = std::get<0>(LHSAndRHS);
1875 auto RHS = std::get<1>(LHSAndRHS);
1876 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1883 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1884 auto LHS = std::get<0>(LHSAndRHS);
1885 auto RHS = std::get<1>(LHSAndRHS);
1886 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1887 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1888 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1889 TargetOpcode::G_ZEXT);
1896 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1897 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1898 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1903 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1907 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1912 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1916 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1919 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1922 LHSPartRegs[
I], RHSPartRegs[
I]);
1923 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1929 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1933 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1938 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1942 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1943 RHSLeftoverRegs[
I]);
1945 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1946 RHSLeftoverRegs[
I]);
1949 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1950 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1956 MI.eraseFromParent();
1959 case TargetOpcode::G_FCMP:
1968 case TargetOpcode::G_SEXT_INREG: {
1972 int64_t SizeInBits =
MI.getOperand(2).getImm();
1981 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
1982 MO1.
setReg(TruncMIB.getReg(0));
1985 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
1997 if (SizeOp0 % NarrowSize != 0)
1999 int NumParts = SizeOp0 / NarrowSize;
2007 for (
int i = 0; i < NumParts; ++i) {
2008 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2023 for (
int i = 0; i < NumParts; ++i) {
2026 PartialExtensionReg = DstRegs.
back();
2028 assert(PartialExtensionReg &&
2029 "Expected to visit partial extension before full");
2030 if (FullExtensionReg) {
2035 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2037 FullExtensionReg = DstRegs.
back();
2042 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2045 PartialExtensionReg = DstRegs.
back();
2051 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2052 MI.eraseFromParent();
2055 case TargetOpcode::G_BSWAP:
2056 case TargetOpcode::G_BITREVERSE: {
2057 if (SizeOp0 % NarrowSize != 0)
2062 unsigned NumParts = SizeOp0 / NarrowSize;
2063 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2066 for (
unsigned i = 0; i < NumParts; ++i) {
2067 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2068 {SrcRegs[NumParts - 1 - i]});
2072 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2075 MI.eraseFromParent();
2078 case TargetOpcode::G_PTR_ADD:
2079 case TargetOpcode::G_PTRMASK: {
2087 case TargetOpcode::G_FPTOUI:
2088 case TargetOpcode::G_FPTOSI:
2089 case TargetOpcode::G_FPTOUI_SAT:
2090 case TargetOpcode::G_FPTOSI_SAT:
2092 case TargetOpcode::G_FPEXT:
2099 case TargetOpcode::G_FLDEXP:
2100 case TargetOpcode::G_STRICT_FLDEXP:
2102 case TargetOpcode::G_VSCALE: {
2104 LLT Ty = MRI.getType(Dst);
2108 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2109 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2110 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2113 MI.eraseFromParent();
2120 LLT Ty = MRI.getType(Val);
2126 if (Ty.isPointer()) {
2127 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2129 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2135 if (Ty.isPointerVector())
2136 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2137 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2141 unsigned OpIdx,
unsigned ExtOpcode) {
2143 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2144 MO.
setReg(ExtB.getReg(0));
2150 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2151 MO.
setReg(ExtB.getReg(0));
2155 unsigned OpIdx,
unsigned TruncOpcode) {
2157 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2159 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2164 unsigned OpIdx,
unsigned ExtOpcode) {
2166 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2168 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2177 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2179 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2185 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2195 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2202LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2207 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2208 if (DstTy.isVector())
2211 LLT SrcTy =
MRI.getType(Src1Reg);
2212 const int DstSize = DstTy.getSizeInBits();
2213 const int SrcSize = SrcTy.getSizeInBits();
2215 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2217 unsigned NumOps =
MI.getNumOperands();
2218 unsigned NumSrc =
MI.getNumOperands() - 1;
2219 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2221 if (WideSize >= DstSize) {
2225 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2226 const unsigned Offset = (
I - 1) * PartSize;
2234 MRI.createGenericVirtualRegister(WideTy);
2239 ResultReg = NextResult;
2242 if (WideSize > DstSize)
2244 else if (DstTy.isPointer())
2247 MI.eraseFromParent();
2272 const int GCD = std::gcd(SrcSize, WideSize);
2282 if (GCD == SrcSize) {
2285 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2286 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2292 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2294 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2298 const int PartsPerGCD = WideSize / GCD;
2302 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2304 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2311 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2313 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2314 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2317 MI.eraseFromParent();
2322LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2327 int NumDst =
MI.getNumOperands() - 1;
2328 Register SrcReg =
MI.getOperand(NumDst).getReg();
2329 LLT SrcTy = MRI.getType(SrcReg);
2333 Register Dst0Reg =
MI.getOperand(0).getReg();
2334 LLT DstTy = MRI.getType(Dst0Reg);
2343 dbgs() <<
"Not casting non-integral address space integer\n");
2348 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2356 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2364 for (
int I = 1;
I != NumDst; ++
I) {
2365 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2366 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2370 MI.eraseFromParent();
2381 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2385 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2388 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2406 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2411 if (PartsPerRemerge == 1) {
2414 for (
int I = 0;
I != NumUnmerge; ++
I) {
2415 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2417 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2418 int Idx =
I * PartsPerUnmerge + J;
2420 MIB.addDef(
MI.getOperand(Idx).getReg());
2423 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2427 MIB.addUse(Unmerge.getReg(
I));
2430 SmallVector<Register, 16> Parts;
2431 for (
int J = 0; J != NumUnmerge; ++J)
2432 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2435 for (
int I = 0;
I != NumDst; ++
I) {
2436 for (
int J = 0; J < PartsPerRemerge; ++J) {
2437 const int Idx =
I * PartsPerRemerge + J;
2441 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2442 RemergeParts.
clear();
2446 MI.eraseFromParent();
2451LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2453 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2454 unsigned Offset =
MI.getOperand(2).getImm();
2457 if (SrcTy.
isVector() || DstTy.isVector())
2469 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2473 if (DstTy.isPointer())
2480 MI.eraseFromParent();
2485 LLT ShiftTy = SrcTy;
2494 MI.eraseFromParent();
2525LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2527 if (TypeIdx != 0 || WideTy.
isVector())
2537LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2541 std::optional<Register> CarryIn;
2542 switch (
MI.getOpcode()) {
2545 case TargetOpcode::G_SADDO:
2546 Opcode = TargetOpcode::G_ADD;
2547 ExtOpcode = TargetOpcode::G_SEXT;
2549 case TargetOpcode::G_SSUBO:
2550 Opcode = TargetOpcode::G_SUB;
2551 ExtOpcode = TargetOpcode::G_SEXT;
2553 case TargetOpcode::G_UADDO:
2554 Opcode = TargetOpcode::G_ADD;
2555 ExtOpcode = TargetOpcode::G_ZEXT;
2557 case TargetOpcode::G_USUBO:
2558 Opcode = TargetOpcode::G_SUB;
2559 ExtOpcode = TargetOpcode::G_ZEXT;
2561 case TargetOpcode::G_SADDE:
2562 Opcode = TargetOpcode::G_UADDE;
2563 ExtOpcode = TargetOpcode::G_SEXT;
2564 CarryIn =
MI.getOperand(4).getReg();
2566 case TargetOpcode::G_SSUBE:
2567 Opcode = TargetOpcode::G_USUBE;
2568 ExtOpcode = TargetOpcode::G_SEXT;
2569 CarryIn =
MI.getOperand(4).getReg();
2571 case TargetOpcode::G_UADDE:
2572 Opcode = TargetOpcode::G_UADDE;
2573 ExtOpcode = TargetOpcode::G_ZEXT;
2574 CarryIn =
MI.getOperand(4).getReg();
2576 case TargetOpcode::G_USUBE:
2577 Opcode = TargetOpcode::G_USUBE;
2578 ExtOpcode = TargetOpcode::G_ZEXT;
2579 CarryIn =
MI.getOperand(4).getReg();
2595 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2596 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2600 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2602 .buildInstr(Opcode, {WideTy, CarryOutTy},
2603 {LHSExt, RHSExt, *CarryIn})
2606 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2608 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2609 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2610 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2615 MI.eraseFromParent();
2620LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2622 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2623 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2624 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2625 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2626 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2639 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2646 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2650 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2651 {ShiftL, ShiftR},
MI.getFlags());
2656 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2659 MI.eraseFromParent();
2664LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2673 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2675 LLT SrcTy = MRI.getType(
LHS);
2676 LLT OverflowTy = MRI.getType(OriginalOverflow);
2683 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2684 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2685 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2692 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2694 MachineInstrBuilder Mulo;
2695 if (WideMulCanOverflow)
2696 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2697 {LeftOperand, RightOperand});
2699 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2704 MachineInstrBuilder ExtResult;
2711 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2715 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2718 if (WideMulCanOverflow) {
2726 MI.eraseFromParent();
2732 unsigned Opcode =
MI.getOpcode();
2736 case TargetOpcode::G_ATOMICRMW_XCHG:
2737 case TargetOpcode::G_ATOMICRMW_ADD:
2738 case TargetOpcode::G_ATOMICRMW_SUB:
2739 case TargetOpcode::G_ATOMICRMW_AND:
2740 case TargetOpcode::G_ATOMICRMW_OR:
2741 case TargetOpcode::G_ATOMICRMW_XOR:
2742 case TargetOpcode::G_ATOMICRMW_MIN:
2743 case TargetOpcode::G_ATOMICRMW_MAX:
2744 case TargetOpcode::G_ATOMICRMW_UMIN:
2745 case TargetOpcode::G_ATOMICRMW_UMAX:
2746 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2752 case TargetOpcode::G_ATOMIC_CMPXCHG:
2753 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2760 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2770 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2775 case TargetOpcode::G_EXTRACT:
2776 return widenScalarExtract(
MI, TypeIdx, WideTy);
2777 case TargetOpcode::G_INSERT:
2778 return widenScalarInsert(
MI, TypeIdx, WideTy);
2779 case TargetOpcode::G_MERGE_VALUES:
2780 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2781 case TargetOpcode::G_UNMERGE_VALUES:
2782 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2783 case TargetOpcode::G_SADDO:
2784 case TargetOpcode::G_SSUBO:
2785 case TargetOpcode::G_UADDO:
2786 case TargetOpcode::G_USUBO:
2787 case TargetOpcode::G_SADDE:
2788 case TargetOpcode::G_SSUBE:
2789 case TargetOpcode::G_UADDE:
2790 case TargetOpcode::G_USUBE:
2791 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2792 case TargetOpcode::G_UMULO:
2793 case TargetOpcode::G_SMULO:
2794 return widenScalarMulo(
MI, TypeIdx, WideTy);
2795 case TargetOpcode::G_SADDSAT:
2796 case TargetOpcode::G_SSUBSAT:
2797 case TargetOpcode::G_SSHLSAT:
2798 case TargetOpcode::G_UADDSAT:
2799 case TargetOpcode::G_USUBSAT:
2800 case TargetOpcode::G_USHLSAT:
2801 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2802 case TargetOpcode::G_CTTZ:
2803 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2804 case TargetOpcode::G_CTLZ:
2805 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
2806 case TargetOpcode::G_CTPOP: {
2817 unsigned ExtOpc = Opcode == TargetOpcode::G_CTTZ ||
2818 Opcode == TargetOpcode::G_CTTZ_ZERO_UNDEF
2819 ? TargetOpcode::G_ANYEXT
2820 : TargetOpcode::G_ZEXT;
2821 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2822 LLT CurTy = MRI.getType(SrcReg);
2823 unsigned NewOpc = Opcode;
2824 if (NewOpc == TargetOpcode::G_CTTZ) {
2831 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2833 NewOpc = TargetOpcode::G_CTTZ_ZERO_UNDEF;
2838 if (Opcode == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
2848 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2850 if (Opcode == TargetOpcode::G_CTLZ) {
2853 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff));
2856 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2857 MI.eraseFromParent();
2860 case TargetOpcode::G_BSWAP: {
2864 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2865 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2866 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2869 MI.getOperand(0).setReg(DstExt);
2873 LLT Ty = MRI.getType(DstReg);
2875 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2876 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2882 case TargetOpcode::G_BITREVERSE: {
2886 LLT Ty = MRI.getType(DstReg);
2889 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2891 MI.getOperand(0).setReg(DstExt);
2894 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2895 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2900 case TargetOpcode::G_FREEZE:
2901 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2908 case TargetOpcode::G_ABS:
2915 case TargetOpcode::G_ADD:
2916 case TargetOpcode::G_AND:
2917 case TargetOpcode::G_MUL:
2918 case TargetOpcode::G_OR:
2919 case TargetOpcode::G_XOR:
2920 case TargetOpcode::G_SUB:
2921 case TargetOpcode::G_SHUFFLE_VECTOR:
2932 case TargetOpcode::G_SBFX:
2933 case TargetOpcode::G_UBFX:
2947 case TargetOpcode::G_SHL:
2963 case TargetOpcode::G_ROTR:
2964 case TargetOpcode::G_ROTL:
2973 case TargetOpcode::G_SDIV:
2974 case TargetOpcode::G_SREM:
2975 case TargetOpcode::G_SMIN:
2976 case TargetOpcode::G_SMAX:
2977 case TargetOpcode::G_ABDS:
2985 case TargetOpcode::G_SDIVREM:
2995 case TargetOpcode::G_ASHR:
2996 case TargetOpcode::G_LSHR:
3000 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3001 : TargetOpcode::G_ZEXT;
3014 case TargetOpcode::G_UDIV:
3015 case TargetOpcode::G_UREM:
3016 case TargetOpcode::G_ABDU:
3023 case TargetOpcode::G_UDIVREM:
3032 case TargetOpcode::G_UMIN:
3033 case TargetOpcode::G_UMAX: {
3034 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3036 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3040 ? TargetOpcode::G_SEXT
3041 : TargetOpcode::G_ZEXT;
3051 case TargetOpcode::G_SELECT:
3061 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3068 case TargetOpcode::G_FPEXT:
3076 case TargetOpcode::G_FPTOSI:
3077 case TargetOpcode::G_FPTOUI:
3078 case TargetOpcode::G_INTRINSIC_LRINT:
3079 case TargetOpcode::G_INTRINSIC_LLRINT:
3080 case TargetOpcode::G_IS_FPCLASS:
3090 case TargetOpcode::G_SITOFP:
3100 case TargetOpcode::G_UITOFP:
3110 case TargetOpcode::G_FPTOSI_SAT:
3111 case TargetOpcode::G_FPTOUI_SAT:
3116 LLT Ty = MRI.getType(OldDst);
3117 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3119 MI.getOperand(0).setReg(ExtReg);
3120 uint64_t ShortBits = Ty.getScalarSizeInBits();
3123 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3134 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3135 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3143 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3151 case TargetOpcode::G_LOAD:
3152 case TargetOpcode::G_SEXTLOAD:
3153 case TargetOpcode::G_ZEXTLOAD:
3159 case TargetOpcode::G_STORE: {
3163 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3164 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3165 if (!Ty.isScalar()) {
3173 MI.setMemRefs(MF, {NewMMO});
3180 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3181 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3187 case TargetOpcode::G_CONSTANT: {
3190 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3191 MRI.getType(
MI.getOperand(0).getReg()));
3192 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3193 ExtOpc == TargetOpcode::G_ANYEXT) &&
3196 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3200 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3206 case TargetOpcode::G_FCONSTANT: {
3212 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3214 MI.eraseFromParent();
3217 case TargetOpcode::G_IMPLICIT_DEF: {
3223 case TargetOpcode::G_BRCOND:
3229 case TargetOpcode::G_FCMP:
3240 case TargetOpcode::G_ICMP:
3245 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3249 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3250 unsigned ExtOpcode =
3254 ? TargetOpcode::G_SEXT
3255 : TargetOpcode::G_ZEXT;
3262 case TargetOpcode::G_PTR_ADD:
3263 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3269 case TargetOpcode::G_PHI: {
3270 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3273 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3285 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3288 LLT VecTy = MRI.getType(VecReg);
3293 TargetOpcode::G_ANYEXT);
3307 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3323 LLT VecTy = MRI.getType(VecReg);
3342 case TargetOpcode::G_FADD:
3343 case TargetOpcode::G_FMUL:
3344 case TargetOpcode::G_FSUB:
3345 case TargetOpcode::G_FMA:
3346 case TargetOpcode::G_FMAD:
3347 case TargetOpcode::G_FNEG:
3348 case TargetOpcode::G_FABS:
3349 case TargetOpcode::G_FCANONICALIZE:
3350 case TargetOpcode::G_FMINNUM:
3351 case TargetOpcode::G_FMAXNUM:
3352 case TargetOpcode::G_FMINNUM_IEEE:
3353 case TargetOpcode::G_FMAXNUM_IEEE:
3354 case TargetOpcode::G_FMINIMUM:
3355 case TargetOpcode::G_FMAXIMUM:
3356 case TargetOpcode::G_FMINIMUMNUM:
3357 case TargetOpcode::G_FMAXIMUMNUM:
3358 case TargetOpcode::G_FDIV:
3359 case TargetOpcode::G_FREM:
3360 case TargetOpcode::G_FCEIL:
3361 case TargetOpcode::G_FFLOOR:
3362 case TargetOpcode::G_FCOS:
3363 case TargetOpcode::G_FSIN:
3364 case TargetOpcode::G_FTAN:
3365 case TargetOpcode::G_FACOS:
3366 case TargetOpcode::G_FASIN:
3367 case TargetOpcode::G_FATAN:
3368 case TargetOpcode::G_FATAN2:
3369 case TargetOpcode::G_FCOSH:
3370 case TargetOpcode::G_FSINH:
3371 case TargetOpcode::G_FTANH:
3372 case TargetOpcode::G_FLOG10:
3373 case TargetOpcode::G_FLOG:
3374 case TargetOpcode::G_FLOG2:
3375 case TargetOpcode::G_FRINT:
3376 case TargetOpcode::G_FNEARBYINT:
3377 case TargetOpcode::G_FSQRT:
3378 case TargetOpcode::G_FEXP:
3379 case TargetOpcode::G_FEXP2:
3380 case TargetOpcode::G_FEXP10:
3381 case TargetOpcode::G_FPOW:
3382 case TargetOpcode::G_INTRINSIC_TRUNC:
3383 case TargetOpcode::G_INTRINSIC_ROUND:
3384 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3388 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3394 case TargetOpcode::G_FMODF: {
3404 case TargetOpcode::G_FPOWI:
3405 case TargetOpcode::G_FLDEXP:
3406 case TargetOpcode::G_STRICT_FLDEXP: {
3408 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3429 case TargetOpcode::G_FFREXP: {
3442 case TargetOpcode::G_LROUND:
3443 case TargetOpcode::G_LLROUND:
3454 case TargetOpcode::G_INTTOPTR:
3462 case TargetOpcode::G_PTRTOINT:
3470 case TargetOpcode::G_BUILD_VECTOR: {
3474 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3480 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3488 case TargetOpcode::G_SEXT_INREG:
3497 case TargetOpcode::G_PTRMASK: {
3505 case TargetOpcode::G_VECREDUCE_ADD: {
3514 case TargetOpcode::G_VECREDUCE_FADD:
3515 case TargetOpcode::G_VECREDUCE_FMUL:
3516 case TargetOpcode::G_VECREDUCE_FMIN:
3517 case TargetOpcode::G_VECREDUCE_FMAX:
3518 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3519 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3524 LLT VecTy = MRI.getType(VecReg);
3533 case TargetOpcode::G_VSCALE: {
3540 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3545 case TargetOpcode::G_SPLAT_VECTOR: {
3554 case TargetOpcode::G_INSERT_SUBVECTOR: {
3562 LLT SubVecTy = MRI.getType(SubVec);
3566 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3567 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3568 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3572 auto SplatZero =
MIRBuilder.buildSplatVector(
3577 MI.eraseFromParent();
3586 auto Unmerge =
B.buildUnmerge(Ty, Src);
3587 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3596 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3598 LLT DstLLT =
MRI.getType(DstReg);
3610 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3619 MI.eraseFromParent();
3630 MI.eraseFromParent();
3637 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3638 if (SrcTy.isVector()) {
3642 if (DstTy.isVector()) {
3643 int NumDstElt = DstTy.getNumElements();
3644 int NumSrcElt = SrcTy.getNumElements();
3647 LLT DstCastTy = DstEltTy;
3648 LLT SrcPartTy = SrcEltTy;
3652 if (NumSrcElt < NumDstElt) {
3662 SrcPartTy = SrcEltTy;
3663 }
else if (NumSrcElt > NumDstElt) {
3674 DstCastTy = DstEltTy;
3679 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3683 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3684 MI.eraseFromParent();
3688 if (DstTy.isVector()) {
3691 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3692 MI.eraseFromParent();
3708 unsigned NewEltSize,
3709 unsigned OldEltSize) {
3710 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3711 LLT IdxTy =
B.getMRI()->getType(Idx);
3714 auto OffsetMask =
B.buildConstant(
3716 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3717 return B.buildShl(IdxTy, OffsetIdx,
3718 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3733 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3737 unsigned OldNumElts = SrcVecTy.getNumElements();
3744 if (NewNumElts > OldNumElts) {
3755 if (NewNumElts % OldNumElts != 0)
3759 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3763 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3766 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3768 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3769 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3770 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3771 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3772 NewOps[
I] = Elt.getReg(0);
3775 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3777 MI.eraseFromParent();
3781 if (NewNumElts < OldNumElts) {
3782 if (NewEltSize % OldEltSize != 0)
3804 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3805 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3808 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3812 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3813 ScaledIdx).getReg(0);
3821 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3823 MI.eraseFromParent();
3837 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3838 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3839 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3840 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3843 auto EltMask =
B.buildConstant(
3847 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3848 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3851 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3855 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3869 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3870 MI.getFirst4RegLLTs();
3882 if (NewNumElts < OldNumElts) {
3883 if (NewEltSize % OldEltSize != 0)
3892 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3893 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3896 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3900 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3901 ScaledIdx).getReg(0);
3911 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3912 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3916 MI.eraseFromParent();
3946 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3950 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3951 return UnableToLegalize;
3956 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3958 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3967 MI.eraseFromParent();
3985 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3986 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3996 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3997 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3999 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4000 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4002 MI.eraseFromParent();
4032 LLT DstTy = MRI.getType(Dst);
4033 LLT SrcTy = MRI.getType(Src);
4039 if (DstTy == CastTy)
4047 if (CastEltSize < DstEltSize)
4050 auto AdjustAmt = CastEltSize / DstEltSize;
4051 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4052 SrcTyMinElts % AdjustAmt != 0)
4057 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4058 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4061 ES->eraseFromParent();
4096 LLT DstTy = MRI.getType(Dst);
4097 LLT BigVecTy = MRI.getType(BigVec);
4098 LLT SubVecTy = MRI.getType(SubVec);
4100 if (DstTy == CastTy)
4115 if (CastEltSize < DstEltSize)
4118 auto AdjustAmt = CastEltSize / DstEltSize;
4119 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4120 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4126 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4127 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4129 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4132 ES->eraseFromParent();
4140 LLT DstTy = MRI.getType(DstReg);
4148 if (MemSizeInBits != MemStoreSizeInBits) {
4165 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4169 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4170 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4172 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4175 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4177 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4180 if (DstTy != LoadTy)
4188 if (
MIRBuilder.getDataLayout().isBigEndian())
4206 uint64_t LargeSplitSize, SmallSplitSize;
4211 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4218 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4221 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4232 if (Alignment.
value() * 8 > MemSizeInBits &&
4237 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4254 LLT PtrTy = MRI.getType(PtrReg);
4257 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4261 LargeSplitSize / 8);
4262 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4263 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4265 SmallPtr, *SmallMMO);
4267 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4268 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4270 if (AnyExtTy == DstTy)
4271 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4273 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4277 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4297 LLT SrcTy = MRI.getType(SrcReg);
4305 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4311 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4313 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4317 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4321 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4336 uint64_t LargeSplitSize, SmallSplitSize;
4343 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4346 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4355 if (SrcTy.isPointer()) {
4357 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4360 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4363 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4364 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4367 LLT PtrTy = MRI.getType(PtrReg);
4370 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4376 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4377 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4386 LLT SrcTy = MRI.getType(SrcReg);
4392 assert(SrcTy.isVector() &&
"Expect a vector store type");
4399 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4403 auto Elt =
MIRBuilder.buildExtractVectorElement(
4404 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4405 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4406 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4412 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4413 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4417 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4428 switch (
MI.getOpcode()) {
4429 case TargetOpcode::G_LOAD: {
4447 case TargetOpcode::G_STORE: {
4463 case TargetOpcode::G_SELECT: {
4467 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4469 dbgs() <<
"bitcast action not implemented for vector select\n");
4480 case TargetOpcode::G_AND:
4481 case TargetOpcode::G_OR:
4482 case TargetOpcode::G_XOR: {
4490 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4492 case TargetOpcode::G_INSERT_VECTOR_ELT:
4494 case TargetOpcode::G_CONCAT_VECTORS:
4496 case TargetOpcode::G_SHUFFLE_VECTOR:
4498 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4500 case TargetOpcode::G_INSERT_SUBVECTOR:
4508void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4518 switch(
MI.getOpcode()) {
4521 case TargetOpcode::G_FCONSTANT:
4523 case TargetOpcode::G_BITCAST:
4525 case TargetOpcode::G_SREM:
4526 case TargetOpcode::G_UREM: {
4527 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4529 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4530 {MI.getOperand(1), MI.getOperand(2)});
4532 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4534 MI.eraseFromParent();
4537 case TargetOpcode::G_SADDO:
4538 case TargetOpcode::G_SSUBO:
4540 case TargetOpcode::G_SADDE:
4542 case TargetOpcode::G_SSUBE:
4544 case TargetOpcode::G_UMULH:
4545 case TargetOpcode::G_SMULH:
4547 case TargetOpcode::G_SMULO:
4548 case TargetOpcode::G_UMULO: {
4551 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4552 LLT Ty = MRI.getType(Res);
4554 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4555 ? TargetOpcode::G_SMULH
4556 : TargetOpcode::G_UMULH;
4560 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4561 MI.removeOperand(1);
4564 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4572 if (Opcode == TargetOpcode::G_SMULH) {
4573 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4574 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4581 case TargetOpcode::G_FNEG: {
4582 auto [Res, SubByReg] =
MI.getFirst2Regs();
4583 LLT Ty = MRI.getType(Res);
4587 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4588 MI.eraseFromParent();
4591 case TargetOpcode::G_FSUB:
4592 case TargetOpcode::G_STRICT_FSUB: {
4593 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4594 LLT Ty = MRI.getType(Res);
4599 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4600 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4604 MI.eraseFromParent();
4607 case TargetOpcode::G_FMAD:
4609 case TargetOpcode::G_FFLOOR:
4611 case TargetOpcode::G_LROUND:
4612 case TargetOpcode::G_LLROUND: {
4615 LLT SrcTy = MRI.getType(SrcReg);
4616 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4619 MI.eraseFromParent();
4622 case TargetOpcode::G_INTRINSIC_ROUND:
4624 case TargetOpcode::G_FRINT: {
4627 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4630 case TargetOpcode::G_INTRINSIC_LRINT:
4631 case TargetOpcode::G_INTRINSIC_LLRINT: {
4634 LLT SrcTy = MRI.getType(SrcReg);
4636 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4638 MI.eraseFromParent();
4641 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4642 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4643 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4644 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4645 **
MI.memoperands_begin());
4647 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4648 MI.eraseFromParent();
4651 case TargetOpcode::G_LOAD:
4652 case TargetOpcode::G_SEXTLOAD:
4653 case TargetOpcode::G_ZEXTLOAD:
4655 case TargetOpcode::G_STORE:
4657 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4658 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4659 case TargetOpcode::G_CTLZ:
4660 case TargetOpcode::G_CTTZ:
4661 case TargetOpcode::G_CTPOP:
4664 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4666 Register NewRes = MRI.cloneVirtualRegister(Res);
4673 MI.eraseFromParent();
4677 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4678 const LLT CondTy = MRI.getType(CarryOut);
4679 const LLT Ty = MRI.getType(Res);
4681 Register NewRes = MRI.cloneVirtualRegister(Res);
4684 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4690 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4691 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4698 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4703 MI.eraseFromParent();
4707 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4712 MI.eraseFromParent();
4716 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4717 const LLT CondTy = MRI.getType(BorrowOut);
4718 const LLT Ty = MRI.getType(Res);
4721 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4727 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4728 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4735 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4736 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4738 MI.eraseFromParent();
4774 case G_MERGE_VALUES:
4776 case G_UNMERGE_VALUES:
4778 case TargetOpcode::G_SEXT_INREG: {
4779 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4780 int64_t SizeInBits =
MI.getOperand(2).getImm();
4782 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4783 LLT DstTy = MRI.getType(DstReg);
4784 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4787 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4788 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4789 MI.eraseFromParent();
4792 case G_EXTRACT_VECTOR_ELT:
4793 case G_INSERT_VECTOR_ELT:
4795 case G_SHUFFLE_VECTOR:
4797 case G_VECTOR_COMPRESS:
4799 case G_DYN_STACKALLOC:
4803 case G_STACKRESTORE:
4813 case G_READ_REGISTER:
4814 case G_WRITE_REGISTER:
4821 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4822 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4828 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4833 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4844 bool IsSigned =
MI.getOpcode() == G_ABDS;
4845 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4846 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4847 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4871 case G_MEMCPY_INLINE:
4872 return lowerMemcpyInline(
MI);
4883 case G_ATOMICRMW_SUB: {
4884 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4885 const LLT ValTy = MRI.getType(Val);
4889 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4890 MI.eraseFromParent();
4913 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4917 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4923 Align StackTypeAlign =
4930 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4931 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4936 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4948 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4951 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4962 "Converting bits to bytes lost precision");
4968 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4969 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4971 if (IdxTy != MRI.getType(Index))
4972 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4977 LLT PtrTy = MRI.getType(VecPtr);
4978 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4986 std::initializer_list<unsigned> NonVecOpIndices) {
4987 if (
MI.getNumMemOperands() != 0)
4990 LLT VecTy =
MRI.getType(
MI.getReg(0));
5004 if (!Ty.isVector()) {
5010 if (Ty.getNumElements() != NumElts)
5025 assert(Ty.isVector() &&
"Expected vector type");
5028 int NumParts, NumLeftover;
5029 std::tie(NumParts, NumLeftover) =
5032 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5033 for (
int i = 0; i < NumParts; ++i) {
5038 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5047 for (
unsigned i = 0; i <
N; ++i) {
5049 Ops.push_back(
Op.getReg());
5050 else if (
Op.isImm())
5051 Ops.push_back(
Op.getImm());
5052 else if (
Op.isPredicate())
5074 std::initializer_list<unsigned> NonVecOpIndices) {
5076 "Non-compatible opcode or not specified non-vector operands");
5077 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5079 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5080 unsigned NumDefs =
MI.getNumDefs();
5088 for (
unsigned i = 0; i < NumDefs; ++i) {
5089 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5097 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5098 ++UseIdx, ++UseNo) {
5101 MI.getOperand(UseIdx));
5110 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5114 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5116 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5117 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5120 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5121 Uses.push_back(InputOpsPieces[InputNo][i]);
5124 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5125 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5130 for (
unsigned i = 0; i < NumDefs; ++i)
5131 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5133 for (
unsigned i = 0; i < NumDefs; ++i)
5134 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5137 MI.eraseFromParent();
5144 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5146 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5147 unsigned NumDefs =
MI.getNumDefs();
5151 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5156 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5157 UseIdx += 2, ++UseNo) {
5165 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5167 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5168 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5170 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5173 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5174 Phi.addUse(InputOpsPieces[j][i]);
5175 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5185 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5187 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5190 MI.eraseFromParent();
5198 const int NumDst =
MI.getNumOperands() - 1;
5199 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5200 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5201 LLT SrcTy = MRI.getType(SrcReg);
5203 if (TypeIdx != 1 || NarrowTy == DstTy)
5210 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5213 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5227 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5228 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5229 const int PartsPerUnmerge = NumDst / NumUnmerge;
5231 for (
int I = 0;
I != NumUnmerge; ++
I) {
5232 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5234 for (
int J = 0; J != PartsPerUnmerge; ++J)
5235 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5236 MIB.addUse(Unmerge.getReg(
I));
5239 MI.eraseFromParent();
5246 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5250 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5252 if (NarrowTy == SrcTy)
5260 assert(SrcTy.isVector() &&
"Expected vector types");
5262 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5276 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5277 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5278 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5284 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5285 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5286 ++i,
Offset += NumNarrowTyElts) {
5289 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5292 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5293 MI.eraseFromParent();
5297 assert(TypeIdx == 0 &&
"Bad type index");
5298 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5313 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5314 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5316 for (
unsigned i = 0; i < NumParts; ++i) {
5318 for (
unsigned j = 0; j < NumElts; ++j)
5319 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5321 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5324 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5325 MI.eraseFromParent();
5333 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5335 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5337 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5339 InsertVal =
MI.getOperand(2).getReg();
5341 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5342 LLT VecTy = MRI.getType(SrcVec);
5348 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5352 MI.eraseFromParent();
5361 SplitPieces[IdxVal] = InsertVal;
5362 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5364 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5368 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5371 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5372 TargetOpcode::G_ANYEXT);
5376 LLT IdxTy = MRI.getType(Idx);
5377 int64_t PartIdx = IdxVal / NewNumElts;
5379 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5382 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5385 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5386 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5387 VecParts[PartIdx] = InsertPart.getReg(0);
5391 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5393 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5397 MI.eraseFromParent();
5417 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5429 LLT ValTy = MRI.getType(ValReg);
5438 int NumLeftover = -1;
5444 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5446 NumParts = NarrowRegs.
size();
5447 NumLeftover = NarrowLeftoverRegs.
size();
5454 LLT PtrTy = MRI.getType(AddrReg);
5457 unsigned TotalSize = ValTy.getSizeInBits();
5464 auto MMO = LdStMI.
getMMO();
5466 unsigned NumParts,
unsigned Offset) ->
unsigned {
5469 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5471 unsigned ByteOffset =
Offset / 8;
5474 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5481 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5482 ValRegs.push_back(Dst);
5483 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5485 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5494 unsigned HandledOffset =
5495 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5499 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5502 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5503 LeftoverTy, NarrowLeftoverRegs);
5517 switch (
MI.getOpcode()) {
5518 case G_IMPLICIT_DEF:
5534 case G_FCANONICALIZE:
5551 case G_INTRINSIC_LRINT:
5552 case G_INTRINSIC_LLRINT:
5553 case G_INTRINSIC_ROUND:
5554 case G_INTRINSIC_ROUNDEVEN:
5557 case G_INTRINSIC_TRUNC:
5585 case G_FMINNUM_IEEE:
5586 case G_FMAXNUM_IEEE:
5608 case G_CTLZ_ZERO_UNDEF:
5610 case G_CTTZ_ZERO_UNDEF:
5626 case G_ADDRSPACE_CAST:
5639 case G_STRICT_FLDEXP:
5648 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5653 case G_UNMERGE_VALUES:
5655 case G_BUILD_VECTOR:
5656 assert(TypeIdx == 0 &&
"not a vector type index");
5658 case G_CONCAT_VECTORS:
5662 case G_EXTRACT_VECTOR_ELT:
5663 case G_INSERT_VECTOR_ELT:
5672 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5673 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5675 case G_SHUFFLE_VECTOR:
5681 case G_INTRINSIC_FPTRUNC_ROUND:
5691 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5692 "Not a bitcast operation");
5697 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5699 unsigned NewElemCount =
5702 if (NewElemCount == 1) {
5705 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5711 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5720 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5721 MI.eraseFromParent();
5727 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5731 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5732 MI.getFirst3RegLLTs();
5735 if (DstTy != Src1Ty)
5737 if (DstTy != Src2Ty)
5752 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5768 unsigned InputUsed[2] = {-1U, -1U};
5769 unsigned FirstMaskIdx =
High * NewElts;
5770 bool UseBuildVector =
false;
5771 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5773 int Idx = Mask[FirstMaskIdx + MaskOffset];
5778 if (
Input >= std::size(Inputs)) {
5785 Idx -=
Input * NewElts;
5789 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5790 if (InputUsed[OpNo] ==
Input) {
5793 }
else if (InputUsed[OpNo] == -1U) {
5795 InputUsed[OpNo] =
Input;
5800 if (OpNo >= std::size(InputUsed)) {
5803 UseBuildVector =
true;
5808 Ops.push_back(Idx + OpNo * NewElts);
5811 if (UseBuildVector) {
5816 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5818 int Idx = Mask[FirstMaskIdx + MaskOffset];
5823 if (
Input >= std::size(Inputs)) {
5830 Idx -=
Input * NewElts;
5834 .buildExtractVectorElement(
5835 EltTy, Inputs[
Input],
5841 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5842 }
else if (InputUsed[0] == -1U) {
5844 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5845 }
else if (NewElts == 1) {
5846 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
5848 Register Op0 = Inputs[InputUsed[0]];
5852 : Inputs[InputUsed[1]];
5854 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5861 MI.eraseFromParent();
5874 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5880 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5883 const unsigned NumParts =
5885 : SrcTy.getNumElements();
5889 if (DstTy != NarrowTy)
5895 unsigned NumPartsLeft = NumParts;
5896 while (NumPartsLeft > 1) {
5897 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5900 .buildInstr(ScalarOpc, {NarrowTy},
5901 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5904 SplitSrcs = PartialResults;
5905 PartialResults.
clear();
5906 NumPartsLeft = SplitSrcs.
size();
5910 MI.eraseFromParent();
5915 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5916 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5919 MI.eraseFromParent();
5923 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5925 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5933 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5936 Register Acc = PartialReductions[0];
5937 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5938 if (Part == NumParts - 1) {
5940 {Acc, PartialReductions[Part]});
5943 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5947 MI.eraseFromParent();
5953 unsigned int TypeIdx,
5955 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5956 MI.getFirst3RegLLTs();
5957 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5961 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5962 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5963 "Unexpected vecreduce opcode");
5964 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5965 ? TargetOpcode::G_FADD
5966 : TargetOpcode::G_FMUL;
5969 unsigned NumParts = SrcTy.getNumElements();
5972 for (
unsigned i = 0; i < NumParts; i++)
5973 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5977 MI.eraseFromParent();
5984 unsigned ScalarOpc) {
5992 while (SplitSrcs.
size() > 1) {
5994 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6002 SplitSrcs = std::move(PartialRdxs);
6006 MI.getOperand(1).setReg(SplitSrcs[0]);
6013 const LLT HalfTy,
const LLT AmtTy) {
6015 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6016 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6020 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6021 MI.eraseFromParent();
6027 unsigned VTBits = 2 * NVTBits;
6030 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6031 if (Amt.
ugt(VTBits)) {
6033 }
else if (Amt.
ugt(NVTBits)) {
6036 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6037 }
else if (Amt == NVTBits) {
6045 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6048 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6049 if (Amt.
ugt(VTBits)) {
6051 }
else if (Amt.
ugt(NVTBits)) {
6053 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6055 }
else if (Amt == NVTBits) {
6059 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6061 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6063 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6069 if (Amt.
ugt(VTBits)) {
6071 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6072 }
else if (Amt.
ugt(NVTBits)) {
6074 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6076 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6077 }
else if (Amt == NVTBits) {
6080 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6082 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6084 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6086 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6093 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6094 MI.eraseFromParent();
6110 LLT DstTy = MRI.getType(DstReg);
6115 LLT ShiftAmtTy = MRI.getType(Amt);
6117 if (DstEltSize % 2 != 0)
6133 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6144 const unsigned NewBitSize = DstEltSize / 2;
6156 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6158 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6159 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6162 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6163 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6165 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6170 switch (
MI.getOpcode()) {
6171 case TargetOpcode::G_SHL: {
6173 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6175 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6176 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6177 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6180 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6181 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6183 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6185 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6187 ResultRegs[0] =
Lo.getReg(0);
6188 ResultRegs[1] =
Hi.getReg(0);
6191 case TargetOpcode::G_LSHR:
6192 case TargetOpcode::G_ASHR: {
6194 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6196 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6197 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6198 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6202 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6205 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6206 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6208 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6212 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6214 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6216 ResultRegs[0] =
Lo.getReg(0);
6217 ResultRegs[1] =
Hi.getReg(0);
6224 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6225 MI.eraseFromParent();
6234 LLT TargetTy,
LLT ShiftAmtTy) {
6237 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6239 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6240 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6241 const bool NeedsInterWordShift = ShiftBits != 0;
6244 case TargetOpcode::G_SHL: {
6247 if (PartIdx < ShiftWords)
6250 unsigned SrcIdx = PartIdx - ShiftWords;
6251 if (!NeedsInterWordShift)
6252 return SrcParts[SrcIdx];
6257 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6261 return Hi.getReg(0);
6264 case TargetOpcode::G_LSHR: {
6265 unsigned SrcIdx = PartIdx + ShiftWords;
6266 if (SrcIdx >= NumParts)
6268 if (!NeedsInterWordShift)
6269 return SrcParts[SrcIdx];
6273 if (SrcIdx + 1 < NumParts) {
6274 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6278 return Lo.getReg(0);
6281 case TargetOpcode::G_ASHR: {
6283 unsigned SrcIdx = PartIdx + ShiftWords;
6284 if (SrcIdx >= NumParts)
6286 if (!NeedsInterWordShift)
6287 return SrcParts[SrcIdx];
6292 (SrcIdx == NumParts - 1)
6296 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6318 unsigned MainOpcode =
6319 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6323 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6332 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6333 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6335 auto IsZeroBitShift =
6343 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6344 : TargetOpcode::G_SHL;
6347 auto TargetBitsConst =
6349 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6354 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6359 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6361 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6365 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6378 LLT DstTy = MRI.getType(DstReg);
6382 const unsigned NumParts = DstBits / TargetBits;
6384 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6394 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6395 MI.eraseFromParent();
6400 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6401 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6407 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6411 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6414 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6415 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6419 for (
unsigned I = 0;
I < NumParts; ++
I)
6421 Params, TargetTy, ShiftAmtTy);
6423 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6424 MI.eraseFromParent();
6433 LLT DstTy = MRI.getType(DstReg);
6434 LLT ShiftAmtTy = MRI.getType(AmtReg);
6438 const unsigned NumParts = DstBits / TargetBits;
6440 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6457 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6469 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6470 auto TargetBitsLog2Const =
6471 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6472 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6475 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6477 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6485 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6486 auto TargetBitsMinusOneConst =
6487 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6489 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6490 TargetBitsMinusOneConst)
6493 FillValue = ZeroReg;
6501 for (
unsigned I = 0;
I < NumParts; ++
I) {
6503 Register InBoundsResult = FillValue;
6513 for (
unsigned K = 0; K < NumParts; ++K) {
6514 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6516 WordShift, WordShiftKConst);
6528 switch (
MI.getOpcode()) {
6529 case TargetOpcode::G_SHL:
6530 MainSrcIdx = (int)
I - (
int)K;
6531 CarrySrcIdx = MainSrcIdx - 1;
6533 case TargetOpcode::G_LSHR:
6534 case TargetOpcode::G_ASHR:
6535 MainSrcIdx = (int)
I + (
int)K;
6536 CarrySrcIdx = MainSrcIdx + 1;
6544 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6545 Register MainOp = SrcParts[MainSrcIdx];
6549 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6550 CarryOp = SrcParts[CarrySrcIdx];
6551 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6552 CarrySrcIdx >= (
int)NumParts)
6553 CarryOp = FillValue;
6559 ResultForK = FillValue;
6565 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6572 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6576 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6577 MI.eraseFromParent();
6584 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6587 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6602 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6607 "getNeutralElementForVecReduce called with invalid opcode!");
6608 case TargetOpcode::G_VECREDUCE_ADD:
6609 case TargetOpcode::G_VECREDUCE_OR:
6610 case TargetOpcode::G_VECREDUCE_XOR:
6611 case TargetOpcode::G_VECREDUCE_UMAX:
6613 case TargetOpcode::G_VECREDUCE_MUL:
6615 case TargetOpcode::G_VECREDUCE_AND:
6616 case TargetOpcode::G_VECREDUCE_UMIN:
6619 case TargetOpcode::G_VECREDUCE_SMAX:
6622 case TargetOpcode::G_VECREDUCE_SMIN:
6625 case TargetOpcode::G_VECREDUCE_FADD:
6627 case TargetOpcode::G_VECREDUCE_FMUL:
6629 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6630 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6631 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6632 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6640 unsigned Opc =
MI.getOpcode();
6642 case TargetOpcode::G_IMPLICIT_DEF:
6643 case TargetOpcode::G_LOAD: {
6651 case TargetOpcode::G_STORE:
6658 case TargetOpcode::G_AND:
6659 case TargetOpcode::G_OR:
6660 case TargetOpcode::G_XOR:
6661 case TargetOpcode::G_ADD:
6662 case TargetOpcode::G_SUB:
6663 case TargetOpcode::G_MUL:
6664 case TargetOpcode::G_FADD:
6665 case TargetOpcode::G_FSUB:
6666 case TargetOpcode::G_FMUL:
6667 case TargetOpcode::G_FDIV:
6668 case TargetOpcode::G_FCOPYSIGN:
6669 case TargetOpcode::G_UADDSAT:
6670 case TargetOpcode::G_USUBSAT:
6671 case TargetOpcode::G_SADDSAT:
6672 case TargetOpcode::G_SSUBSAT:
6673 case TargetOpcode::G_SMIN:
6674 case TargetOpcode::G_SMAX:
6675 case TargetOpcode::G_UMIN:
6676 case TargetOpcode::G_UMAX:
6677 case TargetOpcode::G_FMINNUM:
6678 case TargetOpcode::G_FMAXNUM:
6679 case TargetOpcode::G_FMINNUM_IEEE:
6680 case TargetOpcode::G_FMAXNUM_IEEE:
6681 case TargetOpcode::G_FMINIMUM:
6682 case TargetOpcode::G_FMAXIMUM:
6683 case TargetOpcode::G_FMINIMUMNUM:
6684 case TargetOpcode::G_FMAXIMUMNUM:
6685 case TargetOpcode::G_STRICT_FADD:
6686 case TargetOpcode::G_STRICT_FSUB:
6687 case TargetOpcode::G_STRICT_FMUL:
6688 case TargetOpcode::G_SHL:
6689 case TargetOpcode::G_ASHR:
6690 case TargetOpcode::G_LSHR: {
6698 case TargetOpcode::G_FMA:
6699 case TargetOpcode::G_STRICT_FMA:
6700 case TargetOpcode::G_FSHR:
6701 case TargetOpcode::G_FSHL: {
6710 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6711 case TargetOpcode::G_EXTRACT:
6718 case TargetOpcode::G_INSERT:
6719 case TargetOpcode::G_INSERT_VECTOR_ELT:
6720 case TargetOpcode::G_FREEZE:
6721 case TargetOpcode::G_FNEG:
6722 case TargetOpcode::G_FABS:
6723 case TargetOpcode::G_FSQRT:
6724 case TargetOpcode::G_FCEIL:
6725 case TargetOpcode::G_FFLOOR:
6726 case TargetOpcode::G_FNEARBYINT:
6727 case TargetOpcode::G_FRINT:
6728 case TargetOpcode::G_INTRINSIC_ROUND:
6729 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6730 case TargetOpcode::G_INTRINSIC_TRUNC:
6731 case TargetOpcode::G_BITREVERSE:
6732 case TargetOpcode::G_BSWAP:
6733 case TargetOpcode::G_FCANONICALIZE:
6734 case TargetOpcode::G_SEXT_INREG:
6735 case TargetOpcode::G_ABS:
6736 case TargetOpcode::G_CTLZ:
6737 case TargetOpcode::G_CTPOP:
6745 case TargetOpcode::G_SELECT: {
6746 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6748 if (!CondTy.isScalar() ||
6754 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6756 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6761 if (CondTy.isVector())
6771 case TargetOpcode::G_UNMERGE_VALUES:
6773 case TargetOpcode::G_PHI:
6775 case TargetOpcode::G_SHUFFLE_VECTOR:
6777 case TargetOpcode::G_BUILD_VECTOR: {
6779 for (
auto Op :
MI.uses()) {
6787 MIRBuilder.buildDeleteTrailingVectorElements(
6788 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6789 MI.eraseFromParent();
6792 case TargetOpcode::G_SEXT:
6793 case TargetOpcode::G_ZEXT:
6794 case TargetOpcode::G_ANYEXT:
6795 case TargetOpcode::G_TRUNC:
6796 case TargetOpcode::G_FPTRUNC:
6797 case TargetOpcode::G_FPEXT:
6798 case TargetOpcode::G_FPTOSI:
6799 case TargetOpcode::G_FPTOUI:
6800 case TargetOpcode::G_FPTOSI_SAT:
6801 case TargetOpcode::G_FPTOUI_SAT:
6802 case TargetOpcode::G_SITOFP:
6803 case TargetOpcode::G_UITOFP: {
6811 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6815 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6823 case TargetOpcode::G_ICMP:
6824 case TargetOpcode::G_FCMP: {
6833 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6838 case TargetOpcode::G_BITCAST: {
6842 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6843 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6859 case TargetOpcode::G_VECREDUCE_FADD:
6860 case TargetOpcode::G_VECREDUCE_FMUL:
6861 case TargetOpcode::G_VECREDUCE_ADD:
6862 case TargetOpcode::G_VECREDUCE_MUL:
6863 case TargetOpcode::G_VECREDUCE_AND:
6864 case TargetOpcode::G_VECREDUCE_OR:
6865 case TargetOpcode::G_VECREDUCE_XOR:
6866 case TargetOpcode::G_VECREDUCE_SMAX:
6867 case TargetOpcode::G_VECREDUCE_SMIN:
6868 case TargetOpcode::G_VECREDUCE_UMAX:
6869 case TargetOpcode::G_VECREDUCE_UMIN: {
6870 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6872 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6873 auto NeutralElement = getNeutralElementForVecReduce(
6879 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6880 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6881 NeutralElement, Idx);
6885 MO.
setReg(NewVec.getReg(0));
6897 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6899 unsigned MaskNumElts = Mask.size();
6900 unsigned SrcNumElts = SrcTy.getNumElements();
6903 if (MaskNumElts == SrcNumElts)
6906 if (MaskNumElts < SrcNumElts) {
6914 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6915 MI.getOperand(1).getReg(),
6916 MI.getOperand(2).getReg(), NewMask);
6917 MI.eraseFromParent();
6922 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6923 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6931 MOps1[0] =
MI.getOperand(1).getReg();
6932 MOps2[0] =
MI.getOperand(2).getReg();
6934 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6935 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6939 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6941 if (Idx >=
static_cast<int>(SrcNumElts))
6942 Idx += PaddedMaskNumElts - SrcNumElts;
6947 if (MaskNumElts != PaddedMaskNumElts) {
6949 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6952 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6954 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6959 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6962 MI.eraseFromParent();
6968 unsigned int TypeIdx,
LLT MoreTy) {
6969 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6971 unsigned NumElts = DstTy.getNumElements();
6974 if (DstTy.isVector() && Src1Ty.isVector() &&
6975 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6983 if (DstTy != Src1Ty || DstTy != Src2Ty)
6991 for (
unsigned I = 0;
I != NumElts; ++
I) {
6993 if (Idx <
static_cast<int>(NumElts))
6996 NewMask[
I] = Idx - NumElts + WidenNumElts;
7000 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7001 MI.getOperand(1).getReg(),
7002 MI.getOperand(2).getReg(), NewMask);
7003 MI.eraseFromParent();
7012 unsigned SrcParts = Src1Regs.
size();
7013 unsigned DstParts = DstRegs.
size();
7015 unsigned DstIdx = 0;
7017 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7018 DstRegs[DstIdx] = FactorSum;
7023 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7025 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7026 i <= std::min(DstIdx, SrcParts - 1); ++i) {
7028 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7032 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7033 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7035 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7045 if (DstIdx != DstParts - 1) {
7046 MachineInstrBuilder Uaddo =
7047 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
7048 FactorSum = Uaddo.
getReg(0);
7049 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7050 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7051 MachineInstrBuilder Uaddo =
7052 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
7053 FactorSum = Uaddo.
getReg(0);
7054 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7055 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7059 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7060 for (
unsigned i = 2; i < Factors.
size(); ++i)
7061 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7064 CarrySumPrevDstIdx = CarrySum;
7065 DstRegs[DstIdx] = FactorSum;
7077 LLT DstType = MRI.getType(DstReg);
7079 if (DstType.isVector())
7082 unsigned Opcode =
MI.getOpcode();
7083 unsigned OpO, OpE, OpF;
7085 case TargetOpcode::G_SADDO:
7086 case TargetOpcode::G_SADDE:
7087 case TargetOpcode::G_UADDO:
7088 case TargetOpcode::G_UADDE:
7089 case TargetOpcode::G_ADD:
7090 OpO = TargetOpcode::G_UADDO;
7091 OpE = TargetOpcode::G_UADDE;
7092 OpF = TargetOpcode::G_UADDE;
7093 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7094 OpF = TargetOpcode::G_SADDE;
7096 case TargetOpcode::G_SSUBO:
7097 case TargetOpcode::G_SSUBE:
7098 case TargetOpcode::G_USUBO:
7099 case TargetOpcode::G_USUBE:
7100 case TargetOpcode::G_SUB:
7101 OpO = TargetOpcode::G_USUBO;
7102 OpE = TargetOpcode::G_USUBE;
7103 OpF = TargetOpcode::G_USUBE;
7104 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7105 OpF = TargetOpcode::G_SSUBE;
7112 unsigned NumDefs =
MI.getNumExplicitDefs();
7113 Register Src1 =
MI.getOperand(NumDefs).getReg();
7114 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7117 CarryDst =
MI.getOperand(1).getReg();
7118 if (
MI.getNumOperands() == NumDefs + 3)
7119 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7121 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7122 LLT LeftoverTy, DummyTy;
7124 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7129 int NarrowParts = Src1Regs.
size();
7130 Src1Regs.
append(Src1Left);
7131 Src2Regs.
append(Src2Left);
7134 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7136 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7139 if (i == e - 1 && CarryDst)
7140 CarryOut = CarryDst;
7142 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7145 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7146 {Src1Regs[i], Src2Regs[i]});
7147 }
else if (i == e - 1) {
7148 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7149 {Src1Regs[i], Src2Regs[i], CarryIn});
7151 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7152 {Src1Regs[i], Src2Regs[i], CarryIn});
7158 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7159 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7160 ArrayRef(DstRegs).drop_front(NarrowParts));
7162 MI.eraseFromParent();
7168 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7170 LLT Ty = MRI.getType(DstReg);
7174 unsigned Size = Ty.getSizeInBits();
7176 if (
Size % NarrowSize != 0)
7179 unsigned NumParts =
Size / NarrowSize;
7180 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7181 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7187 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7191 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7192 MI.eraseFromParent();
7202 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7205 LLT SrcTy = MRI.getType(Src);
7216 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7229 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7232 if (SizeOp1 % NarrowSize != 0)
7234 int NumParts = SizeOp1 / NarrowSize;
7237 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7241 uint64_t OpStart =
MI.getOperand(2).getImm();
7242 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7243 for (
int i = 0; i < NumParts; ++i) {
7244 unsigned SrcStart = i * NarrowSize;
7246 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7249 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7257 int64_t ExtractOffset;
7259 if (OpStart < SrcStart) {
7261 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7263 ExtractOffset = OpStart - SrcStart;
7264 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7268 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7270 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7271 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7278 if (MRI.getType(DstReg).isVector())
7279 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7280 else if (DstRegs.
size() > 1)
7281 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7284 MI.eraseFromParent();
7296 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7298 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7301 SrcRegs.
append(LeftoverRegs);
7305 uint64_t OpStart =
MI.getOperand(3).getImm();
7306 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7307 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7308 unsigned DstStart =
I * NarrowSize;
7310 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7318 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7320 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7324 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7332 int64_t ExtractOffset, InsertOffset;
7334 if (OpStart < DstStart) {
7336 ExtractOffset = DstStart - OpStart;
7337 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7339 InsertOffset = OpStart - DstStart;
7342 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7346 if (ExtractOffset != 0 || SegSize != OpSize) {
7348 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7349 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7352 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7353 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7361 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7364 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7366 MI.eraseFromParent();
7374 LLT DstTy = MRI.getType(DstReg);
7376 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7382 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7383 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7387 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7388 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7391 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7392 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7393 {Src0Regs[I], Src1Regs[I]});
7397 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7400 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7401 DstLeftoverRegs.
push_back(Inst.getReg(0));
7404 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7405 LeftoverTy, DstLeftoverRegs);
7407 MI.eraseFromParent();
7417 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7419 LLT DstTy = MRI.getType(DstReg);
7424 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7425 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7426 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7428 MI.eraseFromParent();
7438 Register CondReg =
MI.getOperand(1).getReg();
7439 LLT CondTy = MRI.getType(CondReg);
7444 LLT DstTy = MRI.getType(DstReg);
7450 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7451 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7455 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7456 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7459 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7461 CondReg, Src1Regs[
I], Src2Regs[
I]);
7465 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7467 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7471 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7472 LeftoverTy, DstLeftoverRegs);
7474 MI.eraseFromParent();
7484 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7487 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7488 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7491 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7493 auto C_0 =
B.buildConstant(NarrowTy, 0);
7495 UnmergeSrc.getReg(1), C_0);
7496 auto LoCTLZ = IsUndef ?
7497 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7498 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7499 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7500 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7501 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7502 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7504 MI.eraseFromParent();
7517 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7520 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7521 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7524 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7526 auto C_0 =
B.buildConstant(NarrowTy, 0);
7528 UnmergeSrc.getReg(0), C_0);
7529 auto HiCTTZ = IsUndef ?
7530 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7531 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7532 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7533 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7534 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7535 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7537 MI.eraseFromParent();
7550 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7553 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7554 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7556 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7557 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7558 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7560 MI.eraseFromParent();
7575 LLT ExpTy = MRI.getType(ExpReg);
7580 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7581 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7582 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7583 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7585 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7587 MI.getOperand(2).setReg(Trunc.getReg(0));
7594 unsigned Opc =
MI.getOpcode();
7597 auto QAction = LI.getAction(Q).Action;
7603 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7606 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7610 case TargetOpcode::G_CTLZ: {
7611 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7612 unsigned Len = SrcTy.getScalarSizeInBits();
7614 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7616 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7617 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7620 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7621 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7622 MI.eraseFromParent();
7638 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7639 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7642 Op = MIBOp.getReg(0);
7647 MI.eraseFromParent();
7650 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7653 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7657 case TargetOpcode::G_CTTZ: {
7658 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7660 unsigned Len = SrcTy.getScalarSizeInBits();
7661 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7664 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7665 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7668 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7669 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7670 MI.eraseFromParent();
7677 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7678 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7680 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7681 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7682 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7683 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7686 MI.eraseFromParent();
7690 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7691 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7695 case TargetOpcode::G_CTPOP: {
7697 LLT Ty = MRI.getType(SrcReg);
7698 unsigned Size = Ty.getScalarSizeInBits();
7710 auto C_1 =
B.buildConstant(Ty, 1);
7711 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7713 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7714 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7715 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7719 auto C_2 =
B.buildConstant(Ty, 2);
7720 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7722 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7723 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7724 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7725 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7732 auto C_4 =
B.buildConstant(Ty, 4);
7733 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7734 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7736 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7737 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7739 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7745 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7747 auto IsMulSupported = [
this](
const LLT Ty) {
7748 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7751 if (IsMulSupported(Ty)) {
7752 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7753 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7755 auto ResTmp = B8Count;
7756 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7757 auto ShiftC =
B.buildConstant(Ty, Shift);
7758 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7759 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7761 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7763 MI.eraseFromParent();
7784 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7785 LLT Ty = MRI.getType(Dst);
7786 LLT ShTy = MRI.getType(Z);
7793 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7794 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7799 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7800 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7804 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7817 MI.eraseFromParent();
7823 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7824 LLT Ty = MRI.getType(Dst);
7825 LLT ShTy = MRI.getType(Z);
7828 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7838 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7839 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7840 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7841 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7842 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7846 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7849 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7852 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7854 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7855 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7856 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7859 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7861 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7863 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7866 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7867 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7872 MI.eraseFromParent();
7883 LLT Ty = MRI.getType(Dst);
7884 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7886 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7887 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7890 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7891 return lowerFunnelShiftAsShifts(
MI);
7895 if (Result == UnableToLegalize)
7896 return lowerFunnelShiftAsShifts(
MI);
7901 auto [Dst, Src] =
MI.getFirst2Regs();
7902 LLT DstTy = MRI.getType(Dst);
7903 LLT SrcTy = MRI.getType(Src);
7907 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7915 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7919 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7923 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7928 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7929 {UnmergeSrc.getReg(0)});
7930 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7931 {UnmergeSrc.getReg(1)});
7934 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7936 MI.eraseFromParent();
7953 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7957 LLT DstTy = MRI.getType(DstReg);
7958 LLT SrcTy = MRI.getType(SrcReg);
7966 SrcTy.getElementCount().divideCoefficientBy(2));
7979 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7991 MI.eraseFromParent();
8000 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8001 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8002 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8003 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8004 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8005 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8006 MI.eraseFromParent();
8011 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8013 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8014 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8019 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8020 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8022 return lowerRotateWithReverseRotate(
MI);
8025 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8026 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8027 bool IsFShLegal =
false;
8028 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8029 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8033 MI.eraseFromParent();
8038 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8041 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8046 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8047 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8048 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8054 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8055 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8057 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8063 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8064 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8066 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8068 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8072 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
8073 MI.eraseFromParent();
8081 auto [Dst, Src] =
MI.getFirst2Regs();
8086 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8114 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8127 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8131 MI.eraseFromParent();
8139 auto [Dst, Src] =
MI.getFirst2Regs();
8144 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8157 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8159 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8164 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8166 MI.eraseFromParent();
8174 auto [Dst, Src] =
MI.getFirst2Regs();
8178 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8189 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8190 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8192 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8199 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8200 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8201 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8203 MI.eraseFromParent();
8213 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8219 MI.eraseFromParent();
8224 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8227 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8228 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8229 MIRBuilder.buildSelect(Dst, Src, True, False);
8230 MI.eraseFromParent();
8234 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8254 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8261 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8262 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8263 MIRBuilder.buildSelect(Dst, Src, True, False);
8264 MI.eraseFromParent();
8268 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8291 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8292 MI.eraseFromParent();
8300 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8304 if (SrcTy !=
S64 && SrcTy !=
S32)
8306 if (DstTy !=
S32 && DstTy !=
S64)
8333 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8335 MI.eraseFromParent();
8340 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8345 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8352 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8354 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8355 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8357 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8358 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8360 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8362 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8363 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8364 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8367 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8368 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8369 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8371 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8374 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8379 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8380 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8386 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8388 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8389 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8391 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8396 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8397 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8399 MI.eraseFromParent();
8405 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8407 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8408 unsigned SatWidth = DstTy.getScalarSizeInBits();
8412 APInt MinInt, MaxInt;
8435 if (AreExactFloatBounds) {
8437 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8439 SrcTy.changeElementSize(1), Src, MaxC);
8440 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8442 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8452 MI.eraseFromParent();
8457 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8459 DstTy.changeElementSize(1), Src, Src);
8462 MI.eraseFromParent();
8469 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8478 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8489 MI.eraseFromParent();
8495 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8497 DstTy.changeElementSize(1), Src, Src);
8499 MI.eraseFromParent();
8509 auto [Dst, Src] =
MI.getFirst2Regs();
8511 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8513 if (MRI.getType(Src).isVector())
8517 unsigned Flags =
MI.getFlags();
8520 MI.eraseFromParent();
8524 const unsigned ExpMask = 0x7ff;
8525 const unsigned ExpBiasf64 = 1023;
8526 const unsigned ExpBiasf16 = 15;
8555 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8615 MI.eraseFromParent();
8621 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8625 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8632 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8633 LLT Ty = MRI.getType(Dst);
8635 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8636 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8637 MI.eraseFromParent();
8643 case TargetOpcode::G_SMIN:
8645 case TargetOpcode::G_SMAX:
8647 case TargetOpcode::G_UMIN:
8649 case TargetOpcode::G_UMAX:
8657 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8662 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8663 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8665 MI.eraseFromParent();
8674 LLT DstTy = MRI.getType(Dst);
8675 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8685 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8686 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8688 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8691 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8692 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8693 if (TLI.preferSelectsOverBooleanArithmetic(
8696 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8697 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8699 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8700 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8706 unsigned BoolExtOp =
8708 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8709 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8713 MI.eraseFromParent();
8719 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8720 const int Src0Size = Src0Ty.getScalarSizeInBits();
8721 const int Src1Size = Src1Ty.getScalarSizeInBits();
8726 auto NotSignBitMask =
MIRBuilder.buildConstant(
8731 if (Src0Ty == Src1Ty) {
8732 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8733 }
else if (Src0Size > Src1Size) {
8734 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8735 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8736 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8737 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8739 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8740 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8741 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8742 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8748 unsigned Flags =
MI.getFlags();
8755 MI.eraseFromParent();
8766 switch (
MI.getOpcode()) {
8767 case TargetOpcode::G_FMINNUM:
8768 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8770 case TargetOpcode::G_FMINIMUMNUM:
8771 NewOp = TargetOpcode::G_FMINNUM;
8773 case TargetOpcode::G_FMAXNUM:
8774 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8776 case TargetOpcode::G_FMAXIMUMNUM:
8777 NewOp = TargetOpcode::G_FMAXNUM;
8783 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8784 LLT Ty = MRI.getType(Dst);
8794 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8797 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8802 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8803 MI.eraseFromParent();
8809 unsigned Opc =
MI.getOpcode();
8810 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8811 LLT Ty = MRI.getType(Dst);
8814 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
8816 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
8817 unsigned OpcNonIeee =
8818 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
8819 bool MinMaxMustRespectOrderedZero =
false;
8823 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
8825 MinMaxMustRespectOrderedZero =
true;
8826 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
8831 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
8839 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
8843 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
8845 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
8855 const unsigned Flags =
MI.getFlags();
8861 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
8863 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
8865 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
8867 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
8869 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
8874 MI.eraseFromParent();
8881 LLT Ty = MRI.getType(DstReg);
8882 unsigned Flags =
MI.getFlags();
8887 MI.eraseFromParent();
8893 auto [DstReg,
X] =
MI.getFirst2Regs();
8894 const unsigned Flags =
MI.getFlags();
8895 const LLT Ty = MRI.getType(DstReg);
8907 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8909 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8914 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8915 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8916 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8917 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8919 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8921 MI.eraseFromParent();
8926 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8927 unsigned Flags =
MI.getFlags();
8928 LLT Ty = MRI.getType(DstReg);
8935 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8936 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8939 SrcReg, Zero, Flags);
8941 SrcReg, Trunc, Flags);
8945 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8946 MI.eraseFromParent();
8952 const unsigned NumOps =
MI.getNumOperands();
8953 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8954 unsigned PartSize = Src0Ty.getSizeInBits();
8959 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8960 const unsigned Offset = (
I - 1) * PartSize;
8963 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8966 MRI.createGenericVirtualRegister(WideTy);
8969 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8970 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8971 ResultReg = NextResult;
8974 if (DstTy.isPointer()) {
8975 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8976 DstTy.getAddressSpace())) {
8984 MI.eraseFromParent();
8990 const unsigned NumDst =
MI.getNumOperands() - 1;
8991 Register SrcReg =
MI.getOperand(NumDst).getReg();
8992 Register Dst0Reg =
MI.getOperand(0).getReg();
8993 LLT DstTy = MRI.getType(Dst0Reg);
9002 LLT IntTy = MRI.getType(SrcReg);
9007 unsigned Offset = DstSize;
9008 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9010 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9014 MI.eraseFromParent();
9033 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9034 InsertVal =
MI.getOperand(2).getReg();
9036 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9038 LLT VecTy = MRI.getType(SrcVec);
9048 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9049 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9051 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9054 MI.eraseFromParent();
9059 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9070 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9077 int64_t
Offset = IdxVal * EltBytes;
9088 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9091 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9093 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9096 MI.eraseFromParent();
9102 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9103 MI.getFirst3RegLLTs();
9113 for (
int Idx : Mask) {
9115 if (!Undef.isValid())
9116 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
9121 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9123 int NumElts = Src0Ty.getNumElements();
9124 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9125 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9126 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9128 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9130 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9135 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9136 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9137 MI.eraseFromParent();
9143 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9144 MI.getFirst4RegLLTs();
9146 if (VecTy.isScalableVector())
9162 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9165 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9168 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9171 std::optional<APInt> PassthruSplatVal =
9174 if (PassthruSplatVal.has_value()) {
9176 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9177 }
else if (HasPassthru) {
9178 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9179 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9185 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9189 unsigned NumElmts = VecTy.getNumElements();
9190 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9192 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9195 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9198 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9203 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9205 if (HasPassthru &&
I == NumElmts - 1) {
9208 auto AllLanesSelected =
MIRBuilder.buildICmp(
9210 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9211 {OutPos, EndOfVector});
9215 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9217 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9222 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9224 MI.eraseFromParent();
9235 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9241 if (Alignment >
Align(1)) {
9244 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9253 const auto &MF = *
MI.getMF();
9259 Register AllocSize =
MI.getOperand(1).getReg();
9262 LLT PtrTy = MRI.getType(Dst);
9263 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9270 MI.eraseFromParent();
9276 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9281 MI.eraseFromParent();
9287 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9292 MI.eraseFromParent();
9298 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9299 unsigned Offset =
MI.getOperand(2).getImm();
9302 if (SrcTy.isVector()) {
9303 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9304 unsigned DstSize = DstTy.getSizeInBits();
9306 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9307 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9309 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9313 for (
unsigned Idx =
Offset / SrcEltSize;
9314 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9315 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9317 if (SubVectorElts.
size() == 1)
9318 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9320 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9322 MI.eraseFromParent();
9327 if (DstTy.isScalar() &&
9328 (SrcTy.isScalar() ||
9329 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9330 LLT SrcIntTy = SrcTy;
9331 if (!SrcTy.isScalar()) {
9333 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9340 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9344 MI.eraseFromParent();
9352 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9355 LLT DstTy = MRI.getType(Src);
9356 LLT InsertTy = MRI.getType(InsertSrc);
9364 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9366 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9370 for (; Idx <
Offset / EltSize; ++Idx) {
9371 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9376 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9377 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9379 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9388 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9391 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9392 MI.eraseFromParent();
9406 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9410 LLT IntDstTy = DstTy;
9414 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9419 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9425 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9431 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9432 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9433 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9436 MI.eraseFromParent();
9442 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9443 MI.getFirst4RegLLTs();
9444 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9447 LLT BoolTy = Dst1Ty;
9449 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9466 auto ResultLowerThanLHS =
9471 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9474 MI.eraseFromParent();
9480 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9481 const LLT Ty = MRI.getType(Res);
9484 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9485 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9486 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9497 MI.eraseFromParent();
9502 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9503 const LLT Ty = MRI.getType(Res);
9506 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9507 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9508 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9513 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9518 MI.eraseFromParent();
9524 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9525 LLT Ty = MRI.getType(Res);
9529 switch (
MI.getOpcode()) {
9532 case TargetOpcode::G_UADDSAT:
9535 BaseOp = TargetOpcode::G_ADD;
9537 case TargetOpcode::G_SADDSAT:
9540 BaseOp = TargetOpcode::G_ADD;
9542 case TargetOpcode::G_USUBSAT:
9545 BaseOp = TargetOpcode::G_SUB;
9547 case TargetOpcode::G_SSUBSAT:
9550 BaseOp = TargetOpcode::G_SUB;
9565 uint64_t NumBits = Ty.getScalarSizeInBits();
9576 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9584 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9589 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9590 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9593 MI.eraseFromParent();
9599 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9600 LLT Ty = MRI.getType(Res);
9604 unsigned OverflowOp;
9605 switch (
MI.getOpcode()) {
9608 case TargetOpcode::G_UADDSAT:
9611 OverflowOp = TargetOpcode::G_UADDO;
9613 case TargetOpcode::G_SADDSAT:
9616 OverflowOp = TargetOpcode::G_SADDO;
9618 case TargetOpcode::G_USUBSAT:
9621 OverflowOp = TargetOpcode::G_USUBO;
9623 case TargetOpcode::G_SSUBSAT:
9626 OverflowOp = TargetOpcode::G_SSUBO;
9631 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9632 Register Tmp = OverflowRes.getReg(0);
9633 Register Ov = OverflowRes.getReg(1);
9642 uint64_t NumBits = Ty.getScalarSizeInBits();
9643 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9644 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9647 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9655 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9659 MI.eraseFromParent();
9665 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9666 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9667 "Expected shlsat opcode!");
9668 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9669 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9670 LLT Ty = MRI.getType(Res);
9674 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9675 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9684 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9689 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9691 MI.eraseFromParent();
9696 auto [Dst, Src] =
MI.getFirst2Regs();
9697 const LLT Ty = MRI.getType(Src);
9698 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9699 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9702 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9703 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9704 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9705 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9708 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9710 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9711 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9712 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9714 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9715 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9716 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9718 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9719 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9720 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9722 Res.getInstr()->getOperand(0).setReg(Dst);
9724 MI.eraseFromParent();
9731 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9734 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9735 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9736 return B.buildOr(Dst,
LHS,
RHS);
9741 auto [Dst, Src] =
MI.getFirst2Regs();
9742 const LLT SrcTy = MRI.getType(Src);
9743 unsigned Size = SrcTy.getScalarSizeInBits();
9744 unsigned VSize = SrcTy.getSizeInBits();
9747 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9748 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9749 {LLT::fixed_vector(VSize / 8, 8),
9750 LLT::fixed_vector(VSize / 8, 8)}}))) {
9755 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9756 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9757 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9761 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9784 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9788 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9791 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9795 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9799 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9804 MI.eraseFromParent();
9812 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9813 int NameOpIdx = IsRead ? 1 : 0;
9814 int ValRegIndex = IsRead ? 0 : 1;
9816 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9817 const LLT Ty = MRI.getType(ValReg);
9819 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9826 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9827 Fn,
MI.getDebugLoc()));
9831 MI.eraseFromParent();
9840 MI.eraseFromParent();
9846 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9847 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9849 LLT OrigTy = MRI.getType(Result);
9853 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9854 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9856 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9858 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9859 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9862 MI.eraseFromParent();
9868 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9873 MI.eraseFromParent();
9878 MI.eraseFromParent();
9885 unsigned BitSize = SrcTy.getScalarSizeInBits();
9889 if (SrcTy.isVector())
9890 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9891 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9897 APInt ExpMask = Inf;
9903 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9904 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9905 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9906 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9907 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9909 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9913 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9915 LLT DstTyCopy = DstTy;
9917 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9945 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9948 Mask &= ~PartialCheck;
9957 else if (PartialCheck ==
fcZero)
9969 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9970 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9973 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9975 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9976 appendToRes(SubnormalRes);
9983 else if (PartialCheck ==
fcInf)
9988 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9995 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
9996 if (PartialCheck ==
fcNan) {
10000 }
else if (PartialCheck ==
fcQNan) {
10010 Abs, InfWithQnanBitC);
10011 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10018 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10020 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10021 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10024 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10026 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10029 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10030 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10032 appendToRes(NormalRes);
10036 MI.eraseFromParent();
10042 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10043 MI.getFirst4RegLLTs();
10045 bool IsEltPtr = DstTy.isPointerOrPointerVector();
10049 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10050 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10054 if (MaskTy.isScalar()) {
10062 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10066 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
10068 if (DstTy.isVector()) {
10070 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
10071 MaskReg = ShufSplat.getReg(0);
10076 }
else if (!DstTy.isVector()) {
10081 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10085 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10086 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10087 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10094 MI.eraseFromParent();
10100 unsigned Opcode =
MI.getOpcode();
10103 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10104 : TargetOpcode::G_UDIV,
10105 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10107 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10108 : TargetOpcode::G_UREM,
10109 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10110 MI.eraseFromParent();
10120 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10124 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10127 MI.eraseFromParent();
10137 Register SrcReg =
MI.getOperand(1).getReg();
10138 LLT Ty = MRI.getType(SrcReg);
10139 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10142 MI.eraseFromParent();
10148 Register SrcReg =
MI.getOperand(1).getReg();
10149 Register DestReg =
MI.getOperand(0).getReg();
10151 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10152 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10155 MI.eraseFromParent();
10161 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10162 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10163 "Expected G_ABDS or G_ABDU instruction");
10165 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10166 LLT Ty = MRI.getType(LHS);
10176 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10178 MI.eraseFromParent();
10184 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10185 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10186 "Expected G_ABDS or G_ABDU instruction");
10188 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10189 LLT Ty = MRI.getType(LHS);
10194 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10195 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10196 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10198 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10199 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10201 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10203 MI.eraseFromParent();
10208 Register SrcReg =
MI.getOperand(1).getReg();
10209 Register DstReg =
MI.getOperand(0).getReg();
10211 LLT Ty = MRI.getType(DstReg);
10219 MI.eraseFromParent();
10225 Register SrcReg =
MI.getOperand(1).getReg();
10226 LLT SrcTy = MRI.getType(SrcReg);
10227 LLT DstTy = MRI.getType(SrcReg);
10230 if (SrcTy.isScalar()) {
10235 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10246 Register ListPtr =
MI.getOperand(1).getReg();
10247 LLT PtrTy = MRI.getType(ListPtr);
10254 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10256 const Align A(
MI.getOperand(2).getImm());
10258 if (
A > TLI.getMinStackArgumentAlignment()) {
10260 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10261 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10262 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10263 VAList = AndDst.getReg(0);
10270 LLT LLTTy = MRI.getType(Dst);
10273 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10274 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10279 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10281 Align EltAlignment =
DL.getABITypeAlign(Ty);
10284 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10286 MI.eraseFromParent();
10301 unsigned Limit,
const MemOp &
Op,
10302 unsigned DstAS,
unsigned SrcAS,
10303 const AttributeList &FuncAttributes,
10305 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10315 if (
Op.isFixedDstAlign())
10316 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10319 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10323 unsigned NumMemOps = 0;
10326 unsigned TySize = Ty.getSizeInBytes();
10327 while (TySize >
Size) {
10336 assert(NewTySize > 0 &&
"Could not find appropriate type");
10343 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10345 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10351 TySize = NewTySize;
10355 if (++NumMemOps > Limit)
10358 MemOps.push_back(Ty);
10368 unsigned NumBits = Ty.getScalarSizeInBits();
10370 if (!Ty.isVector() && ValVRegAndVal) {
10371 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10379 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10400 uint64_t KnownLen,
Align Alignment,
10402 auto &MF = *
MI.getParent()->getParent();
10407 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10409 bool DstAlignCanChange =
false;
10413 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10415 DstAlignCanChange =
true;
10417 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10418 std::vector<LLT> MemOps;
10420 const auto &DstMMO = **
MI.memoperands_begin();
10421 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10424 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10435 if (DstAlignCanChange) {
10438 Align NewAlign =
DL.getABITypeAlign(IRTy);
10439 if (NewAlign > Alignment) {
10440 Alignment = NewAlign;
10448 MachineIRBuilder MIB(
MI);
10450 LLT LargestTy = MemOps[0];
10451 for (
unsigned i = 1; i < MemOps.size(); i++)
10453 LargestTy = MemOps[i];
10465 LLT PtrTy = MRI.getType(Dst);
10466 unsigned DstOff = 0;
10467 unsigned Size = KnownLen;
10468 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10469 LLT Ty = MemOps[
I];
10471 if (TySize >
Size) {
10474 assert(
I == MemOps.size() - 1 &&
I != 0);
10475 DstOff -= TySize -
Size;
10485 TLI.isTruncateFree(LargestVT, VT))
10486 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10499 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10502 MIB.buildStore(
Value, Ptr, *StoreMMO);
10507 MI.eraseFromParent();
10513 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10515 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10517 const auto *MMOIt =
MI.memoperands_begin();
10519 bool IsVolatile =
MemOp->isVolatile();
10525 "inline memcpy with dynamic size is not yet supported");
10526 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10527 if (KnownLen == 0) {
10528 MI.eraseFromParent();
10532 const auto &DstMMO = **
MI.memoperands_begin();
10533 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10534 Align DstAlign = DstMMO.getBaseAlign();
10535 Align SrcAlign = SrcMMO.getBaseAlign();
10537 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10544 Align SrcAlign,
bool IsVolatile) {
10545 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10546 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10547 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10554 Align SrcAlign,
bool IsVolatile) {
10555 auto &MF = *
MI.getParent()->getParent();
10560 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10562 bool DstAlignCanChange =
false;
10564 Align Alignment = std::min(DstAlign, SrcAlign);
10568 DstAlignCanChange =
true;
10574 std::vector<LLT> MemOps;
10576 const auto &DstMMO = **
MI.memoperands_begin();
10577 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10583 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10589 if (DstAlignCanChange) {
10592 Align NewAlign =
DL.getABITypeAlign(IRTy);
10597 if (!
TRI->hasStackRealignment(MF))
10599 NewAlign = std::min(NewAlign, *StackAlign);
10601 if (NewAlign > Alignment) {
10602 Alignment = NewAlign;
10610 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10612 MachineIRBuilder MIB(
MI);
10618 unsigned CurrOffset = 0;
10619 unsigned Size = KnownLen;
10620 for (
auto CopyTy : MemOps) {
10623 if (CopyTy.getSizeInBytes() >
Size)
10624 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10635 if (CurrOffset != 0) {
10636 LLT SrcTy = MRI.getType(Src);
10639 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10641 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10645 if (CurrOffset != 0) {
10646 LLT DstTy = MRI.getType(Dst);
10647 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10649 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10650 CurrOffset += CopyTy.getSizeInBytes();
10651 Size -= CopyTy.getSizeInBytes();
10654 MI.eraseFromParent();
10660 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10662 auto &MF = *
MI.getParent()->getParent();
10667 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10669 bool DstAlignCanChange =
false;
10672 Align Alignment = std::min(DstAlign, SrcAlign);
10674 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10676 DstAlignCanChange =
true;
10678 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10679 std::vector<LLT> MemOps;
10681 const auto &DstMMO = **
MI.memoperands_begin();
10682 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10683 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10684 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10691 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10697 if (DstAlignCanChange) {
10700 Align NewAlign =
DL.getABITypeAlign(IRTy);
10705 if (!
TRI->hasStackRealignment(MF))
10706 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10707 NewAlign = std::min(NewAlign, *StackAlign);
10709 if (NewAlign > Alignment) {
10710 Alignment = NewAlign;
10718 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10720 MachineIRBuilder MIB(
MI);
10724 unsigned CurrOffset = 0;
10725 SmallVector<Register, 16> LoadVals;
10726 for (
auto CopyTy : MemOps) {
10733 if (CurrOffset != 0) {
10734 LLT SrcTy = MRI.getType(Src);
10737 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10739 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10740 CurrOffset += CopyTy.getSizeInBytes();
10744 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10745 LLT CopyTy = MemOps[
I];
10751 if (CurrOffset != 0) {
10752 LLT DstTy = MRI.getType(Dst);
10755 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10757 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10760 MI.eraseFromParent();
10766 const unsigned Opc =
MI.getOpcode();
10769 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10770 Opc == TargetOpcode::G_MEMSET) &&
10771 "Expected memcpy like instruction");
10773 auto MMOIt =
MI.memoperands_begin();
10778 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10780 if (
Opc != TargetOpcode::G_MEMSET) {
10781 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10782 MemOp = *(++MMOIt);
10783 SrcAlign =
MemOp->getBaseAlign();
10788 if (!LenVRegAndVal)
10790 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10792 if (KnownLen == 0) {
10793 MI.eraseFromParent();
10797 if (MaxLen && KnownLen > MaxLen)
10800 bool IsVolatile =
MemOp->isVolatile();
10801 if (
Opc == TargetOpcode::G_MEMCPY) {
10802 auto &MF = *
MI.getParent()->getParent();
10805 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10806 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10809 if (
Opc == TargetOpcode::G_MEMMOVE)
10810 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10811 if (
Opc == TargetOpcode::G_MEMSET)
10812 return lowerMemset(
MI, Dst, Src, KnownLen, DstAlign, IsVolatile);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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")
Analysis containing CSE Info
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 bool findGISelOptimalMemOpLowering(std::vector< LLT > &MemOps, unsigned Limit, const MemOp &Op, unsigned DstAS, unsigned SrcAS, const AttributeList &FuncAttributes, const TargetLowering &TLI)
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 LegalizerHelper::LegalizeResult conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, Type *FromType, LostDebugLocObserver &LocObserver, const TargetLowering &TLI, bool IsSigned=false)
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 LegalizerHelper::LegalizeResult simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver)
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 bool shouldLowerMemFuncForSize(const MachineFunction &MF)
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
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 LegalizerHelper::LegalizeResult createAtomicLibcall(MachineIRBuilder &MIRBuilder, MachineInstr &MI)
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)
MachineInstr unsigned OpIdx
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")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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.
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - 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)
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
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.
Register getSubVec() const
Register getBigVec() const
uint64_t getIndexImm() const
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.
Register getValueReg() const
Get the stored value register.
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.
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.
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 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 LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr ElementCount getElementCount() const
constexpr 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.
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 LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr LLT getScalarType() const
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
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 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 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 lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(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 LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI)
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 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 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 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)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ AlreadyLegal
Instruction was already legal and no change was made to the MachineFunction.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFCopySign(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B)
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 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 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 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 lowerVECTOR_COMPRESS(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 lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0)
LLVM_ABI Register coerceToScalar(Register Val)
Cast the given value to an LLT::scalar with an equivalent size.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
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 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 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)
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.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given 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.
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
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.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed 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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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.
MachineInstrBuilder buildXor(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_XOR Op0, Op1.
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 & add(const MachineOperand &MO) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
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.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
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,...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type 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
constexpr const char * data() const
data - 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.
virtual bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *=nullptr) const
Determine if the target supports unaligned memory accesses.
virtual LLT getOptimalMemOpLLT(const MemOp &Op, const AttributeList &) const
LLT returning variant.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const
Returns true if arguments should be sign-extended in lib calls.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
const Triple & getTargetTriple() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const CallLowering * getCallLowering() const
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, DriverKit, XROS, or bridgeOS).
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 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.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ 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.
@ Custom
The target wants to do something special with this combination of operand and type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
FunctionAddr VTableAddr Value
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.
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 std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
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...
LLVM_ABI LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver)
Create a libcall to memcpy et al.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
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)
LLVM_ABI LegalizerHelper::LegalizeResult createLibcall(MachineIRBuilder &MIRBuilder, const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr)
Helper function that creates a libcall to the given Name using the given calling convention CC.
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...
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...
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Next
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 bool isKnownNeverNaN(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the floating-point scalar value is not a NaN or if the floating-point vector value has...
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 isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI)
Returns true if Val can be assumed to never be a signaling NaN.
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.
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.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
bool isKnownNeverZero() const
Return true if it's known this can never be a zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
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.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
static MemOp Set(uint64_t Size, bool DstAlignCanChange, Align DstAlign, bool IsZeroMemset, bool IsVolatile)
static MemOp Copy(uint64_t Size, bool DstAlignCanChange, Align DstAlign, Align SrcAlign, bool IsVolatile, bool MemcpyStrSrc=false)