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_INTTOPTR:
3450 case TargetOpcode::G_PTRTOINT:
3458 case TargetOpcode::G_BUILD_VECTOR: {
3462 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3468 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3476 case TargetOpcode::G_SEXT_INREG:
3485 case TargetOpcode::G_PTRMASK: {
3493 case TargetOpcode::G_VECREDUCE_ADD: {
3502 case TargetOpcode::G_VECREDUCE_FADD:
3503 case TargetOpcode::G_VECREDUCE_FMUL:
3504 case TargetOpcode::G_VECREDUCE_FMIN:
3505 case TargetOpcode::G_VECREDUCE_FMAX:
3506 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3507 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3512 LLT VecTy = MRI.getType(VecReg);
3521 case TargetOpcode::G_VSCALE: {
3528 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3533 case TargetOpcode::G_SPLAT_VECTOR: {
3542 case TargetOpcode::G_INSERT_SUBVECTOR: {
3550 LLT SubVecTy = MRI.getType(SubVec);
3554 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3555 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3556 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3560 auto SplatZero =
MIRBuilder.buildSplatVector(
3565 MI.eraseFromParent();
3574 auto Unmerge =
B.buildUnmerge(Ty, Src);
3575 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3584 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3586 LLT DstLLT =
MRI.getType(DstReg);
3598 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3607 MI.eraseFromParent();
3618 MI.eraseFromParent();
3625 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3626 if (SrcTy.isVector()) {
3630 if (DstTy.isVector()) {
3631 int NumDstElt = DstTy.getNumElements();
3632 int NumSrcElt = SrcTy.getNumElements();
3635 LLT DstCastTy = DstEltTy;
3636 LLT SrcPartTy = SrcEltTy;
3640 if (NumSrcElt < NumDstElt) {
3650 SrcPartTy = SrcEltTy;
3651 }
else if (NumSrcElt > NumDstElt) {
3662 DstCastTy = DstEltTy;
3667 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3671 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3672 MI.eraseFromParent();
3676 if (DstTy.isVector()) {
3679 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3680 MI.eraseFromParent();
3696 unsigned NewEltSize,
3697 unsigned OldEltSize) {
3698 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3699 LLT IdxTy =
B.getMRI()->getType(Idx);
3702 auto OffsetMask =
B.buildConstant(
3704 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3705 return B.buildShl(IdxTy, OffsetIdx,
3706 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3721 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3725 unsigned OldNumElts = SrcVecTy.getNumElements();
3732 if (NewNumElts > OldNumElts) {
3743 if (NewNumElts % OldNumElts != 0)
3747 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3751 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3754 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3756 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3757 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3758 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3759 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3760 NewOps[
I] = Elt.getReg(0);
3763 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3765 MI.eraseFromParent();
3769 if (NewNumElts < OldNumElts) {
3770 if (NewEltSize % OldEltSize != 0)
3792 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3793 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3796 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3800 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3801 ScaledIdx).getReg(0);
3809 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3811 MI.eraseFromParent();
3825 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3826 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3827 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3828 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3831 auto EltMask =
B.buildConstant(
3835 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3836 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3839 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3843 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3857 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3858 MI.getFirst4RegLLTs();
3870 if (NewNumElts < OldNumElts) {
3871 if (NewEltSize % OldEltSize != 0)
3880 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3881 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3884 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3888 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3889 ScaledIdx).getReg(0);
3899 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3900 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3904 MI.eraseFromParent();
3934 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3938 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3939 return UnableToLegalize;
3944 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3946 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3955 MI.eraseFromParent();
3973 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3974 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3984 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3985 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3987 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
3988 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
3990 MI.eraseFromParent();
4020 LLT DstTy = MRI.getType(Dst);
4021 LLT SrcTy = MRI.getType(Src);
4027 if (DstTy == CastTy)
4035 if (CastEltSize < DstEltSize)
4038 auto AdjustAmt = CastEltSize / DstEltSize;
4039 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4040 SrcTyMinElts % AdjustAmt != 0)
4045 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4046 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4049 ES->eraseFromParent();
4084 LLT DstTy = MRI.getType(Dst);
4085 LLT BigVecTy = MRI.getType(BigVec);
4086 LLT SubVecTy = MRI.getType(SubVec);
4088 if (DstTy == CastTy)
4103 if (CastEltSize < DstEltSize)
4106 auto AdjustAmt = CastEltSize / DstEltSize;
4107 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4108 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4114 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4115 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4117 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4120 ES->eraseFromParent();
4128 LLT DstTy = MRI.getType(DstReg);
4136 if (MemSizeInBits != MemStoreSizeInBits) {
4153 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4157 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4158 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4160 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4163 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4165 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4168 if (DstTy != LoadTy)
4176 if (
MIRBuilder.getDataLayout().isBigEndian())
4194 uint64_t LargeSplitSize, SmallSplitSize;
4199 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4206 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4209 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4220 if (Alignment.
value() * 8 > MemSizeInBits &&
4225 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4242 LLT PtrTy = MRI.getType(PtrReg);
4245 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4249 LargeSplitSize / 8);
4250 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4251 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4253 SmallPtr, *SmallMMO);
4255 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4256 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4258 if (AnyExtTy == DstTy)
4259 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4261 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4265 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4285 LLT SrcTy = MRI.getType(SrcReg);
4293 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4299 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4301 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4305 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4309 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4324 uint64_t LargeSplitSize, SmallSplitSize;
4331 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4334 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4343 if (SrcTy.isPointer()) {
4345 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4348 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4351 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4352 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4355 LLT PtrTy = MRI.getType(PtrReg);
4358 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4364 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4365 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4374 LLT SrcTy = MRI.getType(SrcReg);
4380 assert(SrcTy.isVector() &&
"Expect a vector store type");
4387 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4391 auto Elt =
MIRBuilder.buildExtractVectorElement(
4392 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4393 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4394 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4400 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4401 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4405 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4416 switch (
MI.getOpcode()) {
4417 case TargetOpcode::G_LOAD: {
4435 case TargetOpcode::G_STORE: {
4451 case TargetOpcode::G_SELECT: {
4455 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4457 dbgs() <<
"bitcast action not implemented for vector select\n");
4468 case TargetOpcode::G_AND:
4469 case TargetOpcode::G_OR:
4470 case TargetOpcode::G_XOR: {
4478 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4480 case TargetOpcode::G_INSERT_VECTOR_ELT:
4482 case TargetOpcode::G_CONCAT_VECTORS:
4484 case TargetOpcode::G_SHUFFLE_VECTOR:
4486 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4488 case TargetOpcode::G_INSERT_SUBVECTOR:
4496void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4506 switch(
MI.getOpcode()) {
4509 case TargetOpcode::G_FCONSTANT:
4511 case TargetOpcode::G_BITCAST:
4513 case TargetOpcode::G_SREM:
4514 case TargetOpcode::G_UREM: {
4515 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4517 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4518 {MI.getOperand(1), MI.getOperand(2)});
4520 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4522 MI.eraseFromParent();
4525 case TargetOpcode::G_SADDO:
4526 case TargetOpcode::G_SSUBO:
4528 case TargetOpcode::G_SADDE:
4530 case TargetOpcode::G_SSUBE:
4532 case TargetOpcode::G_UMULH:
4533 case TargetOpcode::G_SMULH:
4535 case TargetOpcode::G_SMULO:
4536 case TargetOpcode::G_UMULO: {
4539 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4540 LLT Ty = MRI.getType(Res);
4542 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4543 ? TargetOpcode::G_SMULH
4544 : TargetOpcode::G_UMULH;
4548 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4549 MI.removeOperand(1);
4552 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4560 if (Opcode == TargetOpcode::G_SMULH) {
4561 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4562 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4569 case TargetOpcode::G_FNEG: {
4570 auto [Res, SubByReg] =
MI.getFirst2Regs();
4571 LLT Ty = MRI.getType(Res);
4575 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4576 MI.eraseFromParent();
4579 case TargetOpcode::G_FSUB:
4580 case TargetOpcode::G_STRICT_FSUB: {
4581 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4582 LLT Ty = MRI.getType(Res);
4587 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4588 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4592 MI.eraseFromParent();
4595 case TargetOpcode::G_FMAD:
4597 case TargetOpcode::G_FFLOOR:
4599 case TargetOpcode::G_LROUND:
4600 case TargetOpcode::G_LLROUND: {
4603 LLT SrcTy = MRI.getType(SrcReg);
4604 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4607 MI.eraseFromParent();
4610 case TargetOpcode::G_INTRINSIC_ROUND:
4612 case TargetOpcode::G_FRINT: {
4615 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4618 case TargetOpcode::G_INTRINSIC_LRINT:
4619 case TargetOpcode::G_INTRINSIC_LLRINT: {
4622 LLT SrcTy = MRI.getType(SrcReg);
4624 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4626 MI.eraseFromParent();
4629 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4630 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4631 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4632 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4633 **
MI.memoperands_begin());
4635 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4636 MI.eraseFromParent();
4639 case TargetOpcode::G_LOAD:
4640 case TargetOpcode::G_SEXTLOAD:
4641 case TargetOpcode::G_ZEXTLOAD:
4643 case TargetOpcode::G_STORE:
4645 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4646 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4647 case TargetOpcode::G_CTLZ:
4648 case TargetOpcode::G_CTTZ:
4649 case TargetOpcode::G_CTPOP:
4652 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4654 Register NewRes = MRI.cloneVirtualRegister(Res);
4661 MI.eraseFromParent();
4665 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4666 const LLT CondTy = MRI.getType(CarryOut);
4667 const LLT Ty = MRI.getType(Res);
4669 Register NewRes = MRI.cloneVirtualRegister(Res);
4672 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4678 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4679 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4686 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4691 MI.eraseFromParent();
4695 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4700 MI.eraseFromParent();
4704 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4705 const LLT CondTy = MRI.getType(BorrowOut);
4706 const LLT Ty = MRI.getType(Res);
4709 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4715 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4716 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4723 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4724 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4726 MI.eraseFromParent();
4762 case G_MERGE_VALUES:
4764 case G_UNMERGE_VALUES:
4766 case TargetOpcode::G_SEXT_INREG: {
4767 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4768 int64_t SizeInBits =
MI.getOperand(2).getImm();
4770 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4771 LLT DstTy = MRI.getType(DstReg);
4772 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4775 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4776 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4777 MI.eraseFromParent();
4780 case G_EXTRACT_VECTOR_ELT:
4781 case G_INSERT_VECTOR_ELT:
4783 case G_SHUFFLE_VECTOR:
4785 case G_VECTOR_COMPRESS:
4787 case G_DYN_STACKALLOC:
4791 case G_STACKRESTORE:
4801 case G_READ_REGISTER:
4802 case G_WRITE_REGISTER:
4809 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4810 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4816 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4821 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4832 bool IsSigned =
MI.getOpcode() == G_ABDS;
4833 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4834 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4835 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4859 case G_MEMCPY_INLINE:
4860 return lowerMemcpyInline(
MI);
4871 case G_ATOMICRMW_SUB: {
4872 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4873 const LLT ValTy = MRI.getType(Val);
4877 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4878 MI.eraseFromParent();
4901 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4905 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4911 Align StackTypeAlign =
4918 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4919 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4924 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4936 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4939 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4950 "Converting bits to bytes lost precision");
4956 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4957 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4959 if (IdxTy != MRI.getType(Index))
4960 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4965 LLT PtrTy = MRI.getType(VecPtr);
4966 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4974 std::initializer_list<unsigned> NonVecOpIndices) {
4975 if (
MI.getNumMemOperands() != 0)
4978 LLT VecTy =
MRI.getType(
MI.getReg(0));
4992 if (!Ty.isVector()) {
4998 if (Ty.getNumElements() != NumElts)
5013 assert(Ty.isVector() &&
"Expected vector type");
5016 int NumParts, NumLeftover;
5017 std::tie(NumParts, NumLeftover) =
5020 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5021 for (
int i = 0; i < NumParts; ++i) {
5026 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5035 for (
unsigned i = 0; i <
N; ++i) {
5037 Ops.push_back(
Op.getReg());
5038 else if (
Op.isImm())
5039 Ops.push_back(
Op.getImm());
5040 else if (
Op.isPredicate())
5062 std::initializer_list<unsigned> NonVecOpIndices) {
5064 "Non-compatible opcode or not specified non-vector operands");
5065 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5067 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5068 unsigned NumDefs =
MI.getNumDefs();
5076 for (
unsigned i = 0; i < NumDefs; ++i) {
5077 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5085 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5086 ++UseIdx, ++UseNo) {
5089 MI.getOperand(UseIdx));
5098 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5102 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5104 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5105 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5108 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5109 Uses.push_back(InputOpsPieces[InputNo][i]);
5112 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5113 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5118 for (
unsigned i = 0; i < NumDefs; ++i)
5119 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5121 for (
unsigned i = 0; i < NumDefs; ++i)
5122 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5125 MI.eraseFromParent();
5132 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5134 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5135 unsigned NumDefs =
MI.getNumDefs();
5139 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5144 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5145 UseIdx += 2, ++UseNo) {
5153 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5155 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5156 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5158 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5161 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5162 Phi.addUse(InputOpsPieces[j][i]);
5163 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5173 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5175 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5178 MI.eraseFromParent();
5186 const int NumDst =
MI.getNumOperands() - 1;
5187 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5188 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5189 LLT SrcTy = MRI.getType(SrcReg);
5191 if (TypeIdx != 1 || NarrowTy == DstTy)
5198 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5201 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5215 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5216 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5217 const int PartsPerUnmerge = NumDst / NumUnmerge;
5219 for (
int I = 0;
I != NumUnmerge; ++
I) {
5220 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5222 for (
int J = 0; J != PartsPerUnmerge; ++J)
5223 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5224 MIB.addUse(Unmerge.getReg(
I));
5227 MI.eraseFromParent();
5234 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5238 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5240 if (NarrowTy == SrcTy)
5248 assert(SrcTy.isVector() &&
"Expected vector types");
5250 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5264 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5265 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5266 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5272 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5273 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5274 ++i,
Offset += NumNarrowTyElts) {
5277 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5280 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5281 MI.eraseFromParent();
5285 assert(TypeIdx == 0 &&
"Bad type index");
5286 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5301 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5302 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5304 for (
unsigned i = 0; i < NumParts; ++i) {
5306 for (
unsigned j = 0; j < NumElts; ++j)
5307 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5309 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5312 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5313 MI.eraseFromParent();
5321 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5323 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5325 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5327 InsertVal =
MI.getOperand(2).getReg();
5329 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5330 LLT VecTy = MRI.getType(SrcVec);
5336 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5340 MI.eraseFromParent();
5349 SplitPieces[IdxVal] = InsertVal;
5350 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5352 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5356 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5359 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5360 TargetOpcode::G_ANYEXT);
5364 LLT IdxTy = MRI.getType(Idx);
5365 int64_t PartIdx = IdxVal / NewNumElts;
5367 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5370 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5373 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5374 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5375 VecParts[PartIdx] = InsertPart.getReg(0);
5379 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5381 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5385 MI.eraseFromParent();
5405 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5417 LLT ValTy = MRI.getType(ValReg);
5426 int NumLeftover = -1;
5432 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5434 NumParts = NarrowRegs.
size();
5435 NumLeftover = NarrowLeftoverRegs.
size();
5442 LLT PtrTy = MRI.getType(AddrReg);
5445 unsigned TotalSize = ValTy.getSizeInBits();
5452 auto MMO = LdStMI.
getMMO();
5454 unsigned NumParts,
unsigned Offset) ->
unsigned {
5457 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5459 unsigned ByteOffset =
Offset / 8;
5462 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5469 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5470 ValRegs.push_back(Dst);
5471 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5473 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5482 unsigned HandledOffset =
5483 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5487 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5490 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5491 LeftoverTy, NarrowLeftoverRegs);
5505 switch (
MI.getOpcode()) {
5506 case G_IMPLICIT_DEF:
5522 case G_FCANONICALIZE:
5539 case G_INTRINSIC_LRINT:
5540 case G_INTRINSIC_LLRINT:
5541 case G_INTRINSIC_ROUND:
5542 case G_INTRINSIC_ROUNDEVEN:
5545 case G_INTRINSIC_TRUNC:
5573 case G_FMINNUM_IEEE:
5574 case G_FMAXNUM_IEEE:
5596 case G_CTLZ_ZERO_UNDEF:
5598 case G_CTTZ_ZERO_UNDEF:
5614 case G_ADDRSPACE_CAST:
5627 case G_STRICT_FLDEXP:
5636 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5641 case G_UNMERGE_VALUES:
5643 case G_BUILD_VECTOR:
5644 assert(TypeIdx == 0 &&
"not a vector type index");
5646 case G_CONCAT_VECTORS:
5650 case G_EXTRACT_VECTOR_ELT:
5651 case G_INSERT_VECTOR_ELT:
5660 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5661 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5663 case G_SHUFFLE_VECTOR:
5669 case G_INTRINSIC_FPTRUNC_ROUND:
5679 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5680 "Not a bitcast operation");
5685 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5687 unsigned NewElemCount =
5690 if (NewElemCount == 1) {
5693 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5699 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5708 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5709 MI.eraseFromParent();
5715 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5719 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5720 MI.getFirst3RegLLTs();
5723 if (DstTy != Src1Ty)
5725 if (DstTy != Src2Ty)
5740 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5756 unsigned InputUsed[2] = {-1U, -1U};
5757 unsigned FirstMaskIdx =
High * NewElts;
5758 bool UseBuildVector =
false;
5759 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5761 int Idx = Mask[FirstMaskIdx + MaskOffset];
5766 if (
Input >= std::size(Inputs)) {
5773 Idx -=
Input * NewElts;
5777 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5778 if (InputUsed[OpNo] ==
Input) {
5781 }
else if (InputUsed[OpNo] == -1U) {
5783 InputUsed[OpNo] =
Input;
5788 if (OpNo >= std::size(InputUsed)) {
5791 UseBuildVector =
true;
5796 Ops.push_back(Idx + OpNo * NewElts);
5799 if (UseBuildVector) {
5804 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5806 int Idx = Mask[FirstMaskIdx + MaskOffset];
5811 if (
Input >= std::size(Inputs)) {
5818 Idx -=
Input * NewElts;
5822 .buildExtractVectorElement(
5823 EltTy, Inputs[
Input],
5829 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5830 }
else if (InputUsed[0] == -1U) {
5832 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5833 }
else if (NewElts == 1) {
5834 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
5836 Register Op0 = Inputs[InputUsed[0]];
5840 : Inputs[InputUsed[1]];
5842 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5849 MI.eraseFromParent();
5862 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5868 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5871 const unsigned NumParts =
5873 : SrcTy.getNumElements();
5877 if (DstTy != NarrowTy)
5883 unsigned NumPartsLeft = NumParts;
5884 while (NumPartsLeft > 1) {
5885 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5888 .buildInstr(ScalarOpc, {NarrowTy},
5889 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5892 SplitSrcs = PartialResults;
5893 PartialResults.
clear();
5894 NumPartsLeft = SplitSrcs.
size();
5898 MI.eraseFromParent();
5903 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5904 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5907 MI.eraseFromParent();
5911 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5913 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5921 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5924 Register Acc = PartialReductions[0];
5925 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5926 if (Part == NumParts - 1) {
5928 {Acc, PartialReductions[Part]});
5931 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5935 MI.eraseFromParent();
5941 unsigned int TypeIdx,
5943 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5944 MI.getFirst3RegLLTs();
5945 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5949 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5950 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5951 "Unexpected vecreduce opcode");
5952 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5953 ? TargetOpcode::G_FADD
5954 : TargetOpcode::G_FMUL;
5957 unsigned NumParts = SrcTy.getNumElements();
5960 for (
unsigned i = 0; i < NumParts; i++)
5961 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5965 MI.eraseFromParent();
5972 unsigned ScalarOpc) {
5980 while (SplitSrcs.
size() > 1) {
5982 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
5990 SplitSrcs = std::move(PartialRdxs);
5994 MI.getOperand(1).setReg(SplitSrcs[0]);
6001 const LLT HalfTy,
const LLT AmtTy) {
6003 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6004 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6008 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6009 MI.eraseFromParent();
6015 unsigned VTBits = 2 * NVTBits;
6018 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6019 if (Amt.
ugt(VTBits)) {
6021 }
else if (Amt.
ugt(NVTBits)) {
6024 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6025 }
else if (Amt == NVTBits) {
6033 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6036 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6037 if (Amt.
ugt(VTBits)) {
6039 }
else if (Amt.
ugt(NVTBits)) {
6041 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6043 }
else if (Amt == NVTBits) {
6047 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6049 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6051 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6057 if (Amt.
ugt(VTBits)) {
6059 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6060 }
else if (Amt.
ugt(NVTBits)) {
6062 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6064 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6065 }
else if (Amt == NVTBits) {
6068 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6070 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6072 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6074 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6081 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6082 MI.eraseFromParent();
6098 LLT DstTy = MRI.getType(DstReg);
6103 LLT ShiftAmtTy = MRI.getType(Amt);
6105 if (DstEltSize % 2 != 0)
6121 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6132 const unsigned NewBitSize = DstEltSize / 2;
6144 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6146 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6147 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6150 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6151 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6153 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6158 switch (
MI.getOpcode()) {
6159 case TargetOpcode::G_SHL: {
6161 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6163 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6164 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6165 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6168 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6169 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6171 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6173 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6175 ResultRegs[0] =
Lo.getReg(0);
6176 ResultRegs[1] =
Hi.getReg(0);
6179 case TargetOpcode::G_LSHR:
6180 case TargetOpcode::G_ASHR: {
6182 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6184 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6185 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6186 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6190 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6193 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6194 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6196 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6200 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6202 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6204 ResultRegs[0] =
Lo.getReg(0);
6205 ResultRegs[1] =
Hi.getReg(0);
6212 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6213 MI.eraseFromParent();
6222 LLT TargetTy,
LLT ShiftAmtTy) {
6225 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6227 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6228 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6229 const bool NeedsInterWordShift = ShiftBits != 0;
6232 case TargetOpcode::G_SHL: {
6235 if (PartIdx < ShiftWords)
6238 unsigned SrcIdx = PartIdx - ShiftWords;
6239 if (!NeedsInterWordShift)
6240 return SrcParts[SrcIdx];
6245 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6249 return Hi.getReg(0);
6252 case TargetOpcode::G_LSHR: {
6253 unsigned SrcIdx = PartIdx + ShiftWords;
6254 if (SrcIdx >= NumParts)
6256 if (!NeedsInterWordShift)
6257 return SrcParts[SrcIdx];
6261 if (SrcIdx + 1 < NumParts) {
6262 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6266 return Lo.getReg(0);
6269 case TargetOpcode::G_ASHR: {
6271 unsigned SrcIdx = PartIdx + ShiftWords;
6272 if (SrcIdx >= NumParts)
6274 if (!NeedsInterWordShift)
6275 return SrcParts[SrcIdx];
6280 (SrcIdx == NumParts - 1)
6284 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6306 unsigned MainOpcode =
6307 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6311 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6320 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6321 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6323 auto IsZeroBitShift =
6331 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6332 : TargetOpcode::G_SHL;
6335 auto TargetBitsConst =
6337 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6342 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6347 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6349 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6353 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6366 LLT DstTy = MRI.getType(DstReg);
6370 const unsigned NumParts = DstBits / TargetBits;
6372 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6382 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6383 MI.eraseFromParent();
6388 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6389 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6395 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6399 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6402 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6403 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6407 for (
unsigned I = 0;
I < NumParts; ++
I)
6409 Params, TargetTy, ShiftAmtTy);
6411 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6412 MI.eraseFromParent();
6421 LLT DstTy = MRI.getType(DstReg);
6422 LLT ShiftAmtTy = MRI.getType(AmtReg);
6426 const unsigned NumParts = DstBits / TargetBits;
6428 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6445 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6457 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6458 auto TargetBitsLog2Const =
6459 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6460 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6463 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6465 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6473 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6474 auto TargetBitsMinusOneConst =
6475 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6477 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6478 TargetBitsMinusOneConst)
6481 FillValue = ZeroReg;
6489 for (
unsigned I = 0;
I < NumParts; ++
I) {
6491 Register InBoundsResult = FillValue;
6501 for (
unsigned K = 0; K < NumParts; ++K) {
6502 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6504 WordShift, WordShiftKConst);
6516 switch (
MI.getOpcode()) {
6517 case TargetOpcode::G_SHL:
6518 MainSrcIdx = (int)
I - (
int)K;
6519 CarrySrcIdx = MainSrcIdx - 1;
6521 case TargetOpcode::G_LSHR:
6522 case TargetOpcode::G_ASHR:
6523 MainSrcIdx = (int)
I + (
int)K;
6524 CarrySrcIdx = MainSrcIdx + 1;
6532 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6533 Register MainOp = SrcParts[MainSrcIdx];
6537 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6538 CarryOp = SrcParts[CarrySrcIdx];
6539 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6540 CarrySrcIdx >= (
int)NumParts)
6541 CarryOp = FillValue;
6547 ResultForK = FillValue;
6553 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6560 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6564 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6565 MI.eraseFromParent();
6572 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6575 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6590 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6595 "getNeutralElementForVecReduce called with invalid opcode!");
6596 case TargetOpcode::G_VECREDUCE_ADD:
6597 case TargetOpcode::G_VECREDUCE_OR:
6598 case TargetOpcode::G_VECREDUCE_XOR:
6599 case TargetOpcode::G_VECREDUCE_UMAX:
6601 case TargetOpcode::G_VECREDUCE_MUL:
6603 case TargetOpcode::G_VECREDUCE_AND:
6604 case TargetOpcode::G_VECREDUCE_UMIN:
6607 case TargetOpcode::G_VECREDUCE_SMAX:
6610 case TargetOpcode::G_VECREDUCE_SMIN:
6613 case TargetOpcode::G_VECREDUCE_FADD:
6615 case TargetOpcode::G_VECREDUCE_FMUL:
6617 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6618 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6619 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6620 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6628 unsigned Opc =
MI.getOpcode();
6630 case TargetOpcode::G_IMPLICIT_DEF:
6631 case TargetOpcode::G_LOAD: {
6639 case TargetOpcode::G_STORE:
6646 case TargetOpcode::G_AND:
6647 case TargetOpcode::G_OR:
6648 case TargetOpcode::G_XOR:
6649 case TargetOpcode::G_ADD:
6650 case TargetOpcode::G_SUB:
6651 case TargetOpcode::G_MUL:
6652 case TargetOpcode::G_FADD:
6653 case TargetOpcode::G_FSUB:
6654 case TargetOpcode::G_FMUL:
6655 case TargetOpcode::G_FDIV:
6656 case TargetOpcode::G_FCOPYSIGN:
6657 case TargetOpcode::G_UADDSAT:
6658 case TargetOpcode::G_USUBSAT:
6659 case TargetOpcode::G_SADDSAT:
6660 case TargetOpcode::G_SSUBSAT:
6661 case TargetOpcode::G_SMIN:
6662 case TargetOpcode::G_SMAX:
6663 case TargetOpcode::G_UMIN:
6664 case TargetOpcode::G_UMAX:
6665 case TargetOpcode::G_FMINNUM:
6666 case TargetOpcode::G_FMAXNUM:
6667 case TargetOpcode::G_FMINNUM_IEEE:
6668 case TargetOpcode::G_FMAXNUM_IEEE:
6669 case TargetOpcode::G_FMINIMUM:
6670 case TargetOpcode::G_FMAXIMUM:
6671 case TargetOpcode::G_FMINIMUMNUM:
6672 case TargetOpcode::G_FMAXIMUMNUM:
6673 case TargetOpcode::G_STRICT_FADD:
6674 case TargetOpcode::G_STRICT_FSUB:
6675 case TargetOpcode::G_STRICT_FMUL:
6676 case TargetOpcode::G_SHL:
6677 case TargetOpcode::G_ASHR:
6678 case TargetOpcode::G_LSHR: {
6686 case TargetOpcode::G_FMA:
6687 case TargetOpcode::G_STRICT_FMA:
6688 case TargetOpcode::G_FSHR:
6689 case TargetOpcode::G_FSHL: {
6698 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6699 case TargetOpcode::G_EXTRACT:
6706 case TargetOpcode::G_INSERT:
6707 case TargetOpcode::G_INSERT_VECTOR_ELT:
6708 case TargetOpcode::G_FREEZE:
6709 case TargetOpcode::G_FNEG:
6710 case TargetOpcode::G_FABS:
6711 case TargetOpcode::G_FSQRT:
6712 case TargetOpcode::G_FCEIL:
6713 case TargetOpcode::G_FFLOOR:
6714 case TargetOpcode::G_FNEARBYINT:
6715 case TargetOpcode::G_FRINT:
6716 case TargetOpcode::G_INTRINSIC_ROUND:
6717 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6718 case TargetOpcode::G_INTRINSIC_TRUNC:
6719 case TargetOpcode::G_BITREVERSE:
6720 case TargetOpcode::G_BSWAP:
6721 case TargetOpcode::G_FCANONICALIZE:
6722 case TargetOpcode::G_SEXT_INREG:
6723 case TargetOpcode::G_ABS:
6724 case TargetOpcode::G_CTLZ:
6725 case TargetOpcode::G_CTPOP:
6733 case TargetOpcode::G_SELECT: {
6734 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6736 if (!CondTy.isScalar() ||
6742 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6744 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6749 if (CondTy.isVector())
6759 case TargetOpcode::G_UNMERGE_VALUES:
6761 case TargetOpcode::G_PHI:
6763 case TargetOpcode::G_SHUFFLE_VECTOR:
6765 case TargetOpcode::G_BUILD_VECTOR: {
6767 for (
auto Op :
MI.uses()) {
6775 MIRBuilder.buildDeleteTrailingVectorElements(
6776 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6777 MI.eraseFromParent();
6780 case TargetOpcode::G_SEXT:
6781 case TargetOpcode::G_ZEXT:
6782 case TargetOpcode::G_ANYEXT:
6783 case TargetOpcode::G_TRUNC:
6784 case TargetOpcode::G_FPTRUNC:
6785 case TargetOpcode::G_FPEXT:
6786 case TargetOpcode::G_FPTOSI:
6787 case TargetOpcode::G_FPTOUI:
6788 case TargetOpcode::G_FPTOSI_SAT:
6789 case TargetOpcode::G_FPTOUI_SAT:
6790 case TargetOpcode::G_SITOFP:
6791 case TargetOpcode::G_UITOFP: {
6799 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6803 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6811 case TargetOpcode::G_ICMP:
6812 case TargetOpcode::G_FCMP: {
6821 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6826 case TargetOpcode::G_BITCAST: {
6830 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6831 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6847 case TargetOpcode::G_VECREDUCE_FADD:
6848 case TargetOpcode::G_VECREDUCE_FMUL:
6849 case TargetOpcode::G_VECREDUCE_ADD:
6850 case TargetOpcode::G_VECREDUCE_MUL:
6851 case TargetOpcode::G_VECREDUCE_AND:
6852 case TargetOpcode::G_VECREDUCE_OR:
6853 case TargetOpcode::G_VECREDUCE_XOR:
6854 case TargetOpcode::G_VECREDUCE_SMAX:
6855 case TargetOpcode::G_VECREDUCE_SMIN:
6856 case TargetOpcode::G_VECREDUCE_UMAX:
6857 case TargetOpcode::G_VECREDUCE_UMIN: {
6858 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6860 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6861 auto NeutralElement = getNeutralElementForVecReduce(
6867 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6868 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6869 NeutralElement, Idx);
6873 MO.
setReg(NewVec.getReg(0));
6885 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6887 unsigned MaskNumElts = Mask.size();
6888 unsigned SrcNumElts = SrcTy.getNumElements();
6891 if (MaskNumElts == SrcNumElts)
6894 if (MaskNumElts < SrcNumElts) {
6902 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6903 MI.getOperand(1).getReg(),
6904 MI.getOperand(2).getReg(), NewMask);
6905 MI.eraseFromParent();
6910 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6911 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6919 MOps1[0] =
MI.getOperand(1).getReg();
6920 MOps2[0] =
MI.getOperand(2).getReg();
6922 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6923 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6927 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6929 if (Idx >=
static_cast<int>(SrcNumElts))
6930 Idx += PaddedMaskNumElts - SrcNumElts;
6935 if (MaskNumElts != PaddedMaskNumElts) {
6937 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6940 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6942 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6947 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6950 MI.eraseFromParent();
6956 unsigned int TypeIdx,
LLT MoreTy) {
6957 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6959 unsigned NumElts = DstTy.getNumElements();
6962 if (DstTy.isVector() && Src1Ty.isVector() &&
6963 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6971 if (DstTy != Src1Ty || DstTy != Src2Ty)
6979 for (
unsigned I = 0;
I != NumElts; ++
I) {
6981 if (Idx <
static_cast<int>(NumElts))
6984 NewMask[
I] = Idx - NumElts + WidenNumElts;
6988 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6989 MI.getOperand(1).getReg(),
6990 MI.getOperand(2).getReg(), NewMask);
6991 MI.eraseFromParent();
7000 unsigned SrcParts = Src1Regs.
size();
7001 unsigned DstParts = DstRegs.
size();
7003 unsigned DstIdx = 0;
7005 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7006 DstRegs[DstIdx] = FactorSum;
7011 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7013 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7014 i <= std::min(DstIdx, SrcParts - 1); ++i) {
7016 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7020 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7021 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7023 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7033 if (DstIdx != DstParts - 1) {
7034 MachineInstrBuilder Uaddo =
7035 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
7036 FactorSum = Uaddo.
getReg(0);
7037 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7038 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7039 MachineInstrBuilder Uaddo =
7040 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
7041 FactorSum = Uaddo.
getReg(0);
7042 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7043 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7047 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7048 for (
unsigned i = 2; i < Factors.
size(); ++i)
7049 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7052 CarrySumPrevDstIdx = CarrySum;
7053 DstRegs[DstIdx] = FactorSum;
7065 LLT DstType = MRI.getType(DstReg);
7067 if (DstType.isVector())
7070 unsigned Opcode =
MI.getOpcode();
7071 unsigned OpO, OpE, OpF;
7073 case TargetOpcode::G_SADDO:
7074 case TargetOpcode::G_SADDE:
7075 case TargetOpcode::G_UADDO:
7076 case TargetOpcode::G_UADDE:
7077 case TargetOpcode::G_ADD:
7078 OpO = TargetOpcode::G_UADDO;
7079 OpE = TargetOpcode::G_UADDE;
7080 OpF = TargetOpcode::G_UADDE;
7081 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7082 OpF = TargetOpcode::G_SADDE;
7084 case TargetOpcode::G_SSUBO:
7085 case TargetOpcode::G_SSUBE:
7086 case TargetOpcode::G_USUBO:
7087 case TargetOpcode::G_USUBE:
7088 case TargetOpcode::G_SUB:
7089 OpO = TargetOpcode::G_USUBO;
7090 OpE = TargetOpcode::G_USUBE;
7091 OpF = TargetOpcode::G_USUBE;
7092 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7093 OpF = TargetOpcode::G_SSUBE;
7100 unsigned NumDefs =
MI.getNumExplicitDefs();
7101 Register Src1 =
MI.getOperand(NumDefs).getReg();
7102 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7105 CarryDst =
MI.getOperand(1).getReg();
7106 if (
MI.getNumOperands() == NumDefs + 3)
7107 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7109 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7110 LLT LeftoverTy, DummyTy;
7112 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7117 int NarrowParts = Src1Regs.
size();
7118 Src1Regs.
append(Src1Left);
7119 Src2Regs.
append(Src2Left);
7122 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7124 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7127 if (i == e - 1 && CarryDst)
7128 CarryOut = CarryDst;
7130 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7133 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7134 {Src1Regs[i], Src2Regs[i]});
7135 }
else if (i == e - 1) {
7136 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7137 {Src1Regs[i], Src2Regs[i], CarryIn});
7139 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7140 {Src1Regs[i], Src2Regs[i], CarryIn});
7146 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7147 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7148 ArrayRef(DstRegs).drop_front(NarrowParts));
7150 MI.eraseFromParent();
7156 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7158 LLT Ty = MRI.getType(DstReg);
7162 unsigned Size = Ty.getSizeInBits();
7164 if (
Size % NarrowSize != 0)
7167 unsigned NumParts =
Size / NarrowSize;
7168 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7169 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7175 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7179 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7180 MI.eraseFromParent();
7190 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7193 LLT SrcTy = MRI.getType(Src);
7204 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7217 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7220 if (SizeOp1 % NarrowSize != 0)
7222 int NumParts = SizeOp1 / NarrowSize;
7225 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7229 uint64_t OpStart =
MI.getOperand(2).getImm();
7230 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7231 for (
int i = 0; i < NumParts; ++i) {
7232 unsigned SrcStart = i * NarrowSize;
7234 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7237 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7245 int64_t ExtractOffset;
7247 if (OpStart < SrcStart) {
7249 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7251 ExtractOffset = OpStart - SrcStart;
7252 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7256 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7258 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7259 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7266 if (MRI.getType(DstReg).isVector())
7267 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7268 else if (DstRegs.
size() > 1)
7269 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7272 MI.eraseFromParent();
7284 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7286 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7289 SrcRegs.
append(LeftoverRegs);
7293 uint64_t OpStart =
MI.getOperand(3).getImm();
7294 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7295 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7296 unsigned DstStart =
I * NarrowSize;
7298 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7306 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7308 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7312 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7320 int64_t ExtractOffset, InsertOffset;
7322 if (OpStart < DstStart) {
7324 ExtractOffset = DstStart - OpStart;
7325 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7327 InsertOffset = OpStart - DstStart;
7330 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7334 if (ExtractOffset != 0 || SegSize != OpSize) {
7336 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7337 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7340 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7341 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7349 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7352 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7354 MI.eraseFromParent();
7362 LLT DstTy = MRI.getType(DstReg);
7364 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7370 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7371 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7375 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7376 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7379 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7380 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7381 {Src0Regs[I], Src1Regs[I]});
7385 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7388 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7389 DstLeftoverRegs.
push_back(Inst.getReg(0));
7392 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7393 LeftoverTy, DstLeftoverRegs);
7395 MI.eraseFromParent();
7405 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7407 LLT DstTy = MRI.getType(DstReg);
7412 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7413 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7414 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7416 MI.eraseFromParent();
7426 Register CondReg =
MI.getOperand(1).getReg();
7427 LLT CondTy = MRI.getType(CondReg);
7432 LLT DstTy = MRI.getType(DstReg);
7438 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7439 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7443 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7444 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7447 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7449 CondReg, Src1Regs[
I], Src2Regs[
I]);
7453 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7455 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7459 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7460 LeftoverTy, DstLeftoverRegs);
7462 MI.eraseFromParent();
7472 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7475 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7476 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7479 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7481 auto C_0 =
B.buildConstant(NarrowTy, 0);
7483 UnmergeSrc.getReg(1), C_0);
7484 auto LoCTLZ = IsUndef ?
7485 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7486 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7487 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7488 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7489 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7490 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7492 MI.eraseFromParent();
7505 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7508 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7509 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7512 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7514 auto C_0 =
B.buildConstant(NarrowTy, 0);
7516 UnmergeSrc.getReg(0), C_0);
7517 auto HiCTTZ = IsUndef ?
7518 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7519 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7520 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7521 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7522 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7523 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7525 MI.eraseFromParent();
7538 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7541 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7542 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7544 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7545 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7546 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7548 MI.eraseFromParent();
7563 LLT ExpTy = MRI.getType(ExpReg);
7568 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7569 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7570 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7571 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7573 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7575 MI.getOperand(2).setReg(Trunc.getReg(0));
7582 unsigned Opc =
MI.getOpcode();
7585 auto QAction = LI.getAction(Q).Action;
7591 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7594 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7598 case TargetOpcode::G_CTLZ: {
7599 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7600 unsigned Len = SrcTy.getSizeInBits();
7602 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7604 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7605 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7608 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7609 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7610 MI.eraseFromParent();
7626 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7627 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7630 Op = MIBOp.getReg(0);
7635 MI.eraseFromParent();
7638 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7641 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7645 case TargetOpcode::G_CTTZ: {
7646 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7648 unsigned Len = SrcTy.getSizeInBits();
7649 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7652 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7653 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7656 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7657 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7658 MI.eraseFromParent();
7665 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7666 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7668 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7669 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7670 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7671 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7674 MI.eraseFromParent();
7678 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7679 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7683 case TargetOpcode::G_CTPOP: {
7685 LLT Ty = MRI.getType(SrcReg);
7686 unsigned Size = Ty.getSizeInBits();
7694 auto C_1 =
B.buildConstant(Ty, 1);
7695 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7697 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7698 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7699 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7703 auto C_2 =
B.buildConstant(Ty, 2);
7704 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7706 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7707 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7708 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7709 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7716 auto C_4 =
B.buildConstant(Ty, 4);
7717 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7718 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7720 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7721 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7723 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7729 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7731 auto IsMulSupported = [
this](
const LLT Ty) {
7732 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7735 if (IsMulSupported(Ty)) {
7736 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7737 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7739 auto ResTmp = B8Count;
7740 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7741 auto ShiftC =
B.buildConstant(Ty, Shift);
7742 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7743 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7745 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7747 MI.eraseFromParent();
7768 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7769 LLT Ty = MRI.getType(Dst);
7770 LLT ShTy = MRI.getType(Z);
7777 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7778 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7783 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7784 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7788 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7801 MI.eraseFromParent();
7807 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7808 LLT Ty = MRI.getType(Dst);
7809 LLT ShTy = MRI.getType(Z);
7812 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7822 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7823 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7824 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7825 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7826 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7830 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7833 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7836 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7838 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7839 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7840 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7843 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7845 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7847 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7850 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7851 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7856 MI.eraseFromParent();
7867 LLT Ty = MRI.getType(Dst);
7868 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7870 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7871 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7874 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7875 return lowerFunnelShiftAsShifts(
MI);
7879 if (Result == UnableToLegalize)
7880 return lowerFunnelShiftAsShifts(
MI);
7885 auto [Dst, Src] =
MI.getFirst2Regs();
7886 LLT DstTy = MRI.getType(Dst);
7887 LLT SrcTy = MRI.getType(Src);
7891 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7899 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7903 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7907 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7912 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7913 {UnmergeSrc.getReg(0)});
7914 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7915 {UnmergeSrc.getReg(1)});
7918 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7920 MI.eraseFromParent();
7937 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7941 LLT DstTy = MRI.getType(DstReg);
7942 LLT SrcTy = MRI.getType(SrcReg);
7950 SrcTy.getElementCount().divideCoefficientBy(2));
7963 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7975 MI.eraseFromParent();
7984 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7985 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
7986 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7987 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7988 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
7989 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
7990 MI.eraseFromParent();
7995 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7997 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
7998 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8003 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8004 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8006 return lowerRotateWithReverseRotate(
MI);
8009 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8010 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8011 bool IsFShLegal =
false;
8012 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8013 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8017 MI.eraseFromParent();
8022 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8025 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8030 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8031 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8032 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8038 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8039 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8041 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8047 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8048 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8050 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8052 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8056 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
8057 MI.eraseFromParent();
8065 auto [Dst, Src] =
MI.getFirst2Regs();
8070 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8098 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8111 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8115 MI.eraseFromParent();
8123 auto [Dst, Src] =
MI.getFirst2Regs();
8128 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8141 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8143 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8148 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8150 MI.eraseFromParent();
8158 auto [Dst, Src] =
MI.getFirst2Regs();
8162 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8173 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8174 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8176 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8183 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8184 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8185 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8187 MI.eraseFromParent();
8197 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8203 MI.eraseFromParent();
8208 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8211 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8212 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8213 MIRBuilder.buildSelect(Dst, Src, True, False);
8214 MI.eraseFromParent();
8218 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8238 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8245 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8246 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8247 MIRBuilder.buildSelect(Dst, Src, True, False);
8248 MI.eraseFromParent();
8252 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8275 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8276 MI.eraseFromParent();
8284 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8288 if (SrcTy !=
S64 && SrcTy !=
S32)
8290 if (DstTy !=
S32 && DstTy !=
S64)
8317 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8319 MI.eraseFromParent();
8324 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8329 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8336 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8338 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8339 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8341 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8342 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8344 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8346 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8347 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8348 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8351 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8352 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8353 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8355 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8358 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8363 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8364 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8370 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8372 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8373 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8375 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8380 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8381 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8383 MI.eraseFromParent();
8389 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8391 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8392 unsigned SatWidth = DstTy.getScalarSizeInBits();
8396 APInt MinInt, MaxInt;
8419 if (AreExactFloatBounds) {
8421 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8423 SrcTy.changeElementSize(1), Src, MaxC);
8424 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8426 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8436 MI.eraseFromParent();
8441 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8443 DstTy.changeElementSize(1), Src, Src);
8446 MI.eraseFromParent();
8453 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8462 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8473 MI.eraseFromParent();
8479 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8481 DstTy.changeElementSize(1), Src, Src);
8483 MI.eraseFromParent();
8493 auto [Dst, Src] =
MI.getFirst2Regs();
8495 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8497 if (MRI.getType(Src).isVector())
8501 unsigned Flags =
MI.getFlags();
8504 MI.eraseFromParent();
8508 const unsigned ExpMask = 0x7ff;
8509 const unsigned ExpBiasf64 = 1023;
8510 const unsigned ExpBiasf16 = 15;
8539 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8599 MI.eraseFromParent();
8605 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8609 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8616 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8617 LLT Ty = MRI.getType(Dst);
8619 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8620 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8621 MI.eraseFromParent();
8627 case TargetOpcode::G_SMIN:
8629 case TargetOpcode::G_SMAX:
8631 case TargetOpcode::G_UMIN:
8633 case TargetOpcode::G_UMAX:
8641 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8646 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8647 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8649 MI.eraseFromParent();
8658 LLT DstTy = MRI.getType(Dst);
8659 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8669 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8670 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8672 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8675 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8676 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8677 if (TLI.preferSelectsOverBooleanArithmetic(
8680 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8681 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8683 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8684 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8690 unsigned BoolExtOp =
8692 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8693 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8697 MI.eraseFromParent();
8703 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8704 const int Src0Size = Src0Ty.getScalarSizeInBits();
8705 const int Src1Size = Src1Ty.getScalarSizeInBits();
8710 auto NotSignBitMask =
MIRBuilder.buildConstant(
8715 if (Src0Ty == Src1Ty) {
8716 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8717 }
else if (Src0Size > Src1Size) {
8718 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8719 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8720 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8721 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8723 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8724 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8725 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8726 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8732 unsigned Flags =
MI.getFlags();
8739 MI.eraseFromParent();
8750 switch (
MI.getOpcode()) {
8751 case TargetOpcode::G_FMINNUM:
8752 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8754 case TargetOpcode::G_FMINIMUMNUM:
8755 NewOp = TargetOpcode::G_FMINNUM;
8757 case TargetOpcode::G_FMAXNUM:
8758 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8760 case TargetOpcode::G_FMAXIMUMNUM:
8761 NewOp = TargetOpcode::G_FMAXNUM;
8767 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8768 LLT Ty = MRI.getType(Dst);
8778 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8781 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8786 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8787 MI.eraseFromParent();
8793 unsigned Opc =
MI.getOpcode();
8794 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8795 LLT Ty = MRI.getType(Dst);
8798 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
8800 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
8801 unsigned OpcNonIeee =
8802 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
8803 bool MinMaxMustRespectOrderedZero =
false;
8807 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
8809 MinMaxMustRespectOrderedZero =
true;
8810 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
8815 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
8823 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
8827 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
8829 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
8839 const unsigned Flags =
MI.getFlags();
8845 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
8847 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
8849 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
8851 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
8853 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
8858 MI.eraseFromParent();
8865 LLT Ty = MRI.getType(DstReg);
8866 unsigned Flags =
MI.getFlags();
8871 MI.eraseFromParent();
8877 auto [DstReg,
X] =
MI.getFirst2Regs();
8878 const unsigned Flags =
MI.getFlags();
8879 const LLT Ty = MRI.getType(DstReg);
8891 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8893 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8898 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8899 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8900 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8901 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8903 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8905 MI.eraseFromParent();
8910 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8911 unsigned Flags =
MI.getFlags();
8912 LLT Ty = MRI.getType(DstReg);
8919 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8920 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8923 SrcReg, Zero, Flags);
8925 SrcReg, Trunc, Flags);
8929 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8930 MI.eraseFromParent();
8936 const unsigned NumOps =
MI.getNumOperands();
8937 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8938 unsigned PartSize = Src0Ty.getSizeInBits();
8943 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8944 const unsigned Offset = (
I - 1) * PartSize;
8947 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8950 MRI.createGenericVirtualRegister(WideTy);
8953 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8954 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8955 ResultReg = NextResult;
8958 if (DstTy.isPointer()) {
8959 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8960 DstTy.getAddressSpace())) {
8968 MI.eraseFromParent();
8974 const unsigned NumDst =
MI.getNumOperands() - 1;
8975 Register SrcReg =
MI.getOperand(NumDst).getReg();
8976 Register Dst0Reg =
MI.getOperand(0).getReg();
8977 LLT DstTy = MRI.getType(Dst0Reg);
8986 LLT IntTy = MRI.getType(SrcReg);
8991 unsigned Offset = DstSize;
8992 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
8994 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
8998 MI.eraseFromParent();
9017 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9018 InsertVal =
MI.getOperand(2).getReg();
9020 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9022 LLT VecTy = MRI.getType(SrcVec);
9032 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9033 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9035 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9038 MI.eraseFromParent();
9043 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9054 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9061 int64_t
Offset = IdxVal * EltBytes;
9072 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9075 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9077 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9080 MI.eraseFromParent();
9086 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9087 MI.getFirst3RegLLTs();
9097 for (
int Idx : Mask) {
9099 if (!Undef.isValid())
9100 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
9105 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9107 int NumElts = Src0Ty.getNumElements();
9108 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9109 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9110 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9112 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9114 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9119 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9120 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9121 MI.eraseFromParent();
9127 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9128 MI.getFirst4RegLLTs();
9130 if (VecTy.isScalableVector())
9146 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9149 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9152 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9155 std::optional<APInt> PassthruSplatVal =
9158 if (PassthruSplatVal.has_value()) {
9160 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9161 }
else if (HasPassthru) {
9162 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9163 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9169 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9173 unsigned NumElmts = VecTy.getNumElements();
9174 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9176 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9179 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9182 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9187 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9189 if (HasPassthru &&
I == NumElmts - 1) {
9192 auto AllLanesSelected =
MIRBuilder.buildICmp(
9194 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9195 {OutPos, EndOfVector});
9199 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9201 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9206 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9208 MI.eraseFromParent();
9219 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9225 if (Alignment >
Align(1)) {
9228 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9237 const auto &MF = *
MI.getMF();
9243 Register AllocSize =
MI.getOperand(1).getReg();
9246 LLT PtrTy = MRI.getType(Dst);
9247 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9254 MI.eraseFromParent();
9260 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9265 MI.eraseFromParent();
9271 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9276 MI.eraseFromParent();
9282 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9283 unsigned Offset =
MI.getOperand(2).getImm();
9286 if (SrcTy.isVector()) {
9287 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9288 unsigned DstSize = DstTy.getSizeInBits();
9290 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9291 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9293 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9297 for (
unsigned Idx =
Offset / SrcEltSize;
9298 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9299 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9301 if (SubVectorElts.
size() == 1)
9302 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9304 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9306 MI.eraseFromParent();
9311 if (DstTy.isScalar() &&
9312 (SrcTy.isScalar() ||
9313 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9314 LLT SrcIntTy = SrcTy;
9315 if (!SrcTy.isScalar()) {
9317 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9324 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9328 MI.eraseFromParent();
9336 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9339 LLT DstTy = MRI.getType(Src);
9340 LLT InsertTy = MRI.getType(InsertSrc);
9348 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9350 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9354 for (; Idx <
Offset / EltSize; ++Idx) {
9355 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9360 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9361 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9363 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9372 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9375 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9376 MI.eraseFromParent();
9390 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9394 LLT IntDstTy = DstTy;
9398 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9403 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9409 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9415 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9416 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9417 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9420 MI.eraseFromParent();
9426 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9427 MI.getFirst4RegLLTs();
9428 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9431 LLT BoolTy = Dst1Ty;
9433 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9450 auto ResultLowerThanLHS =
9455 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9458 MI.eraseFromParent();
9464 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9465 const LLT Ty = MRI.getType(Res);
9468 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9469 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9470 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9481 MI.eraseFromParent();
9486 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9487 const LLT Ty = MRI.getType(Res);
9490 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9491 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9492 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9497 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9502 MI.eraseFromParent();
9508 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9509 LLT Ty = MRI.getType(Res);
9513 switch (
MI.getOpcode()) {
9516 case TargetOpcode::G_UADDSAT:
9519 BaseOp = TargetOpcode::G_ADD;
9521 case TargetOpcode::G_SADDSAT:
9524 BaseOp = TargetOpcode::G_ADD;
9526 case TargetOpcode::G_USUBSAT:
9529 BaseOp = TargetOpcode::G_SUB;
9531 case TargetOpcode::G_SSUBSAT:
9534 BaseOp = TargetOpcode::G_SUB;
9549 uint64_t NumBits = Ty.getScalarSizeInBits();
9560 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9568 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9573 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9574 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9577 MI.eraseFromParent();
9583 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9584 LLT Ty = MRI.getType(Res);
9588 unsigned OverflowOp;
9589 switch (
MI.getOpcode()) {
9592 case TargetOpcode::G_UADDSAT:
9595 OverflowOp = TargetOpcode::G_UADDO;
9597 case TargetOpcode::G_SADDSAT:
9600 OverflowOp = TargetOpcode::G_SADDO;
9602 case TargetOpcode::G_USUBSAT:
9605 OverflowOp = TargetOpcode::G_USUBO;
9607 case TargetOpcode::G_SSUBSAT:
9610 OverflowOp = TargetOpcode::G_SSUBO;
9615 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9616 Register Tmp = OverflowRes.getReg(0);
9617 Register Ov = OverflowRes.getReg(1);
9626 uint64_t NumBits = Ty.getScalarSizeInBits();
9627 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9628 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9631 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9639 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9643 MI.eraseFromParent();
9649 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9650 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9651 "Expected shlsat opcode!");
9652 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9653 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9654 LLT Ty = MRI.getType(Res);
9658 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9659 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9668 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9673 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9675 MI.eraseFromParent();
9680 auto [Dst, Src] =
MI.getFirst2Regs();
9681 const LLT Ty = MRI.getType(Src);
9682 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9683 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9686 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9687 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9688 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9689 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9692 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9694 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9695 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9696 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9698 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9699 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9700 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9702 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9703 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9704 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9706 Res.getInstr()->getOperand(0).setReg(Dst);
9708 MI.eraseFromParent();
9715 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9718 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9719 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9720 return B.buildOr(Dst,
LHS,
RHS);
9725 auto [Dst, Src] =
MI.getFirst2Regs();
9726 const LLT SrcTy = MRI.getType(Src);
9727 unsigned Size = SrcTy.getScalarSizeInBits();
9728 unsigned VSize = SrcTy.getSizeInBits();
9731 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9732 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9733 {LLT::fixed_vector(VSize / 8, 8),
9734 LLT::fixed_vector(VSize / 8, 8)}}))) {
9739 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9740 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9741 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9745 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9768 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9772 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9775 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9779 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9783 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9788 MI.eraseFromParent();
9796 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9797 int NameOpIdx = IsRead ? 1 : 0;
9798 int ValRegIndex = IsRead ? 0 : 1;
9800 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9801 const LLT Ty = MRI.getType(ValReg);
9803 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9810 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9811 Fn,
MI.getDebugLoc()));
9815 MI.eraseFromParent();
9824 MI.eraseFromParent();
9830 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9831 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9833 LLT OrigTy = MRI.getType(Result);
9837 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9838 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9840 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9842 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9843 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9846 MI.eraseFromParent();
9852 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9857 MI.eraseFromParent();
9862 MI.eraseFromParent();
9869 unsigned BitSize = SrcTy.getScalarSizeInBits();
9873 if (SrcTy.isVector())
9874 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9875 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9881 APInt ExpMask = Inf;
9887 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9888 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9889 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9890 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9891 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9893 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9897 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9899 LLT DstTyCopy = DstTy;
9901 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9929 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9932 Mask &= ~PartialCheck;
9941 else if (PartialCheck ==
fcZero)
9953 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9954 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9957 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9959 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9960 appendToRes(SubnormalRes);
9967 else if (PartialCheck ==
fcInf)
9972 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9979 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
9980 if (PartialCheck ==
fcNan) {
9984 }
else if (PartialCheck ==
fcQNan) {
9994 Abs, InfWithQnanBitC);
9995 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10002 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10004 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10005 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10008 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10010 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10013 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10014 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10016 appendToRes(NormalRes);
10020 MI.eraseFromParent();
10026 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10027 MI.getFirst4RegLLTs();
10029 bool IsEltPtr = DstTy.isPointerOrPointerVector();
10033 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10034 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10038 if (MaskTy.isScalar()) {
10046 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10050 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
10052 if (DstTy.isVector()) {
10054 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
10055 MaskReg = ShufSplat.getReg(0);
10060 }
else if (!DstTy.isVector()) {
10065 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10069 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10070 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10071 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10078 MI.eraseFromParent();
10084 unsigned Opcode =
MI.getOpcode();
10087 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10088 : TargetOpcode::G_UDIV,
10089 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10091 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10092 : TargetOpcode::G_UREM,
10093 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10094 MI.eraseFromParent();
10104 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10108 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10111 MI.eraseFromParent();
10121 Register SrcReg =
MI.getOperand(1).getReg();
10122 LLT Ty = MRI.getType(SrcReg);
10123 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10126 MI.eraseFromParent();
10132 Register SrcReg =
MI.getOperand(1).getReg();
10133 Register DestReg =
MI.getOperand(0).getReg();
10135 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10136 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10139 MI.eraseFromParent();
10145 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10146 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10147 "Expected G_ABDS or G_ABDU instruction");
10149 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10150 LLT Ty = MRI.getType(LHS);
10160 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10162 MI.eraseFromParent();
10168 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10169 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10170 "Expected G_ABDS or G_ABDU instruction");
10172 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10173 LLT Ty = MRI.getType(LHS);
10178 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10179 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10180 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10182 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10183 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10185 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10187 MI.eraseFromParent();
10192 Register SrcReg =
MI.getOperand(1).getReg();
10193 Register DstReg =
MI.getOperand(0).getReg();
10195 LLT Ty = MRI.getType(DstReg);
10203 MI.eraseFromParent();
10209 Register SrcReg =
MI.getOperand(1).getReg();
10210 LLT SrcTy = MRI.getType(SrcReg);
10211 LLT DstTy = MRI.getType(SrcReg);
10214 if (SrcTy.isScalar()) {
10219 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10230 Register ListPtr =
MI.getOperand(1).getReg();
10231 LLT PtrTy = MRI.getType(ListPtr);
10238 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10240 const Align A(
MI.getOperand(2).getImm());
10242 if (
A > TLI.getMinStackArgumentAlignment()) {
10244 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10245 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10246 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10247 VAList = AndDst.getReg(0);
10254 LLT LLTTy = MRI.getType(Dst);
10257 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10258 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10263 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10265 Align EltAlignment =
DL.getABITypeAlign(Ty);
10268 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10270 MI.eraseFromParent();
10285 unsigned Limit,
const MemOp &
Op,
10286 unsigned DstAS,
unsigned SrcAS,
10287 const AttributeList &FuncAttributes,
10289 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10299 if (
Op.isFixedDstAlign())
10300 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10303 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10307 unsigned NumMemOps = 0;
10310 unsigned TySize = Ty.getSizeInBytes();
10311 while (TySize >
Size) {
10320 assert(NewTySize > 0 &&
"Could not find appropriate type");
10327 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10329 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10335 TySize = NewTySize;
10339 if (++NumMemOps > Limit)
10342 MemOps.push_back(Ty);
10352 unsigned NumBits = Ty.getScalarSizeInBits();
10354 if (!Ty.isVector() && ValVRegAndVal) {
10355 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10363 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10384 uint64_t KnownLen,
Align Alignment,
10386 auto &MF = *
MI.getParent()->getParent();
10391 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10393 bool DstAlignCanChange =
false;
10397 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10399 DstAlignCanChange =
true;
10401 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10402 std::vector<LLT> MemOps;
10404 const auto &DstMMO = **
MI.memoperands_begin();
10405 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10408 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10419 if (DstAlignCanChange) {
10422 Align NewAlign =
DL.getABITypeAlign(IRTy);
10423 if (NewAlign > Alignment) {
10424 Alignment = NewAlign;
10432 MachineIRBuilder MIB(
MI);
10434 LLT LargestTy = MemOps[0];
10435 for (
unsigned i = 1; i < MemOps.size(); i++)
10437 LargestTy = MemOps[i];
10449 LLT PtrTy = MRI.getType(Dst);
10450 unsigned DstOff = 0;
10451 unsigned Size = KnownLen;
10452 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10453 LLT Ty = MemOps[
I];
10455 if (TySize >
Size) {
10458 assert(
I == MemOps.size() - 1 &&
I != 0);
10459 DstOff -= TySize -
Size;
10469 TLI.isTruncateFree(LargestVT, VT))
10470 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10483 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10486 MIB.buildStore(
Value,
Ptr, *StoreMMO);
10491 MI.eraseFromParent();
10497 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10499 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10501 const auto *MMOIt =
MI.memoperands_begin();
10503 bool IsVolatile =
MemOp->isVolatile();
10509 "inline memcpy with dynamic size is not yet supported");
10510 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10511 if (KnownLen == 0) {
10512 MI.eraseFromParent();
10516 const auto &DstMMO = **
MI.memoperands_begin();
10517 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10518 Align DstAlign = DstMMO.getBaseAlign();
10519 Align SrcAlign = SrcMMO.getBaseAlign();
10521 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10528 Align SrcAlign,
bool IsVolatile) {
10529 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10530 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10531 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10538 Align SrcAlign,
bool IsVolatile) {
10539 auto &MF = *
MI.getParent()->getParent();
10544 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10546 bool DstAlignCanChange =
false;
10548 Align Alignment = std::min(DstAlign, SrcAlign);
10552 DstAlignCanChange =
true;
10558 std::vector<LLT> MemOps;
10560 const auto &DstMMO = **
MI.memoperands_begin();
10561 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10567 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10573 if (DstAlignCanChange) {
10576 Align NewAlign =
DL.getABITypeAlign(IRTy);
10581 if (!
TRI->hasStackRealignment(MF))
10583 NewAlign = std::min(NewAlign, *StackAlign);
10585 if (NewAlign > Alignment) {
10586 Alignment = NewAlign;
10594 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10596 MachineIRBuilder MIB(
MI);
10602 unsigned CurrOffset = 0;
10603 unsigned Size = KnownLen;
10604 for (
auto CopyTy : MemOps) {
10607 if (CopyTy.getSizeInBytes() >
Size)
10608 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10619 if (CurrOffset != 0) {
10620 LLT SrcTy = MRI.getType(Src);
10623 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10625 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10629 if (CurrOffset != 0) {
10630 LLT DstTy = MRI.getType(Dst);
10631 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10633 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10634 CurrOffset += CopyTy.getSizeInBytes();
10635 Size -= CopyTy.getSizeInBytes();
10638 MI.eraseFromParent();
10644 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10646 auto &MF = *
MI.getParent()->getParent();
10651 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10653 bool DstAlignCanChange =
false;
10656 Align Alignment = std::min(DstAlign, SrcAlign);
10658 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10660 DstAlignCanChange =
true;
10662 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10663 std::vector<LLT> MemOps;
10665 const auto &DstMMO = **
MI.memoperands_begin();
10666 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10667 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10668 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10675 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10681 if (DstAlignCanChange) {
10684 Align NewAlign =
DL.getABITypeAlign(IRTy);
10689 if (!
TRI->hasStackRealignment(MF))
10690 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10691 NewAlign = std::min(NewAlign, *StackAlign);
10693 if (NewAlign > Alignment) {
10694 Alignment = NewAlign;
10702 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10704 MachineIRBuilder MIB(
MI);
10708 unsigned CurrOffset = 0;
10709 SmallVector<Register, 16> LoadVals;
10710 for (
auto CopyTy : MemOps) {
10717 if (CurrOffset != 0) {
10718 LLT SrcTy = MRI.getType(Src);
10721 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10723 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10724 CurrOffset += CopyTy.getSizeInBytes();
10728 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10729 LLT CopyTy = MemOps[
I];
10735 if (CurrOffset != 0) {
10736 LLT DstTy = MRI.getType(Dst);
10739 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10741 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10744 MI.eraseFromParent();
10750 const unsigned Opc =
MI.getOpcode();
10753 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10754 Opc == TargetOpcode::G_MEMSET) &&
10755 "Expected memcpy like instruction");
10757 auto MMOIt =
MI.memoperands_begin();
10762 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10764 if (
Opc != TargetOpcode::G_MEMSET) {
10765 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10766 MemOp = *(++MMOIt);
10767 SrcAlign =
MemOp->getBaseAlign();
10772 if (!LenVRegAndVal)
10774 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10776 if (KnownLen == 0) {
10777 MI.eraseFromParent();
10781 if (MaxLen && KnownLen > MaxLen)
10784 bool IsVolatile =
MemOp->isVolatile();
10785 if (
Opc == TargetOpcode::G_MEMCPY) {
10786 auto &MF = *
MI.getParent()->getParent();
10789 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10790 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10793 if (
Opc == TargetOpcode::G_MEMMOVE)
10794 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10795 if (
Opc == TargetOpcode::G_MEMSET)
10796 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)