43#define DEBUG_TYPE "legalizer"
56static std::pair<int, int>
62 unsigned NumParts =
Size / NarrowSize;
63 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
66 if (LeftoverSize == 0)
71 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
127 auto Step = LI.getAction(
MI, MRI);
128 switch (Step.Action) {
143 return bitcast(
MI, Step.TypeIdx, Step.NewType);
146 return lower(
MI, Step.TypeIdx, Step.NewType);
155 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
163void LegalizerHelper::insertParts(
Register DstReg,
185 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
187 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
188 return mergeMixedSubvectors(DstReg, AllRegs);
194 extractGCDType(GCDRegs, GCDTy, PartReg);
195 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
196 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
201 LLT Ty = MRI.getType(
Reg);
209void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
212 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
213 appendVectorElts(AllElts, PartRegs[i]);
216 if (!MRI.getType(Leftover).isVector())
219 appendVectorElts(AllElts, Leftover);
221 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
227 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
229 const int StartIdx = Regs.
size();
230 const int NumResults =
MI.getNumOperands() - 1;
232 for (
int I = 0;
I != NumResults; ++
I)
233 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
238 LLT SrcTy = MRI.getType(SrcReg);
239 if (SrcTy == GCDTy) {
245 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
252 LLT SrcTy = MRI.getType(SrcReg);
254 extractGCDType(Parts, GCDTy, SrcReg);
258LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
260 unsigned PadStrategy) {
265 int NumOrigSrc = VRegs.
size();
271 if (NumOrigSrc < NumParts * NumSubParts) {
272 if (PadStrategy == TargetOpcode::G_ZEXT)
273 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
274 else if (PadStrategy == TargetOpcode::G_ANYEXT)
275 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
277 assert(PadStrategy == TargetOpcode::G_SEXT);
282 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
298 for (
int I = 0;
I != NumParts; ++
I) {
299 bool AllMergePartsArePadding =
true;
302 for (
int J = 0; J != NumSubParts; ++J) {
303 int Idx =
I * NumSubParts + J;
304 if (Idx >= NumOrigSrc) {
305 SubMerge[J] = PadReg;
309 SubMerge[J] = VRegs[Idx];
312 AllMergePartsArePadding =
false;
318 if (AllMergePartsArePadding && !AllPadReg) {
319 if (PadStrategy == TargetOpcode::G_ANYEXT)
320 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
321 else if (PadStrategy == TargetOpcode::G_ZEXT)
322 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
331 Remerge[
I] = AllPadReg;
335 if (NumSubParts == 1)
336 Remerge[
I] = SubMerge[0];
338 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
341 if (AllMergePartsArePadding && !AllPadReg)
342 AllPadReg = Remerge[
I];
345 VRegs = std::move(Remerge);
349void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
351 LLT DstTy = MRI.getType(DstReg);
356 if (DstTy == LCMTy) {
357 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
361 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
370 UnmergeDefs[0] = DstReg;
371 for (
unsigned I = 1;
I != NumDefs; ++
I)
372 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
375 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
383#define RTLIBCASE_INT(LibcallPrefix) \
387 return RTLIB::LibcallPrefix##32; \
389 return RTLIB::LibcallPrefix##64; \
391 return RTLIB::LibcallPrefix##128; \
393 llvm_unreachable("unexpected size"); \
397#define RTLIBCASE(LibcallPrefix) \
401 return RTLIB::LibcallPrefix##32; \
403 return RTLIB::LibcallPrefix##64; \
405 return RTLIB::LibcallPrefix##80; \
407 return RTLIB::LibcallPrefix##128; \
409 llvm_unreachable("unexpected size"); \
414 case TargetOpcode::G_LROUND:
416 case TargetOpcode::G_LLROUND:
418 case TargetOpcode::G_MUL:
420 case TargetOpcode::G_SDIV:
422 case TargetOpcode::G_UDIV:
424 case TargetOpcode::G_SREM:
426 case TargetOpcode::G_UREM:
428 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
430 case TargetOpcode::G_FADD:
432 case TargetOpcode::G_FSUB:
434 case TargetOpcode::G_FMUL:
436 case TargetOpcode::G_FDIV:
438 case TargetOpcode::G_FEXP:
440 case TargetOpcode::G_FEXP2:
442 case TargetOpcode::G_FEXP10:
444 case TargetOpcode::G_FREM:
446 case TargetOpcode::G_FPOW:
448 case TargetOpcode::G_FPOWI:
450 case TargetOpcode::G_FMA:
452 case TargetOpcode::G_FSIN:
454 case TargetOpcode::G_FCOS:
456 case TargetOpcode::G_FTAN:
458 case TargetOpcode::G_FASIN:
460 case TargetOpcode::G_FACOS:
462 case TargetOpcode::G_FATAN:
464 case TargetOpcode::G_FATAN2:
466 case TargetOpcode::G_FSINH:
468 case TargetOpcode::G_FCOSH:
470 case TargetOpcode::G_FTANH:
472 case TargetOpcode::G_FSINCOS:
474 case TargetOpcode::G_FMODF:
476 case TargetOpcode::G_FLOG10:
478 case TargetOpcode::G_FLOG:
480 case TargetOpcode::G_FLOG2:
482 case TargetOpcode::G_FLDEXP:
484 case TargetOpcode::G_FCEIL:
486 case TargetOpcode::G_FFLOOR:
488 case TargetOpcode::G_FMINNUM:
490 case TargetOpcode::G_FMAXNUM:
492 case TargetOpcode::G_FMINIMUMNUM:
494 case TargetOpcode::G_FMAXIMUMNUM:
496 case TargetOpcode::G_FSQRT:
498 case TargetOpcode::G_FRINT:
500 case TargetOpcode::G_FNEARBYINT:
502 case TargetOpcode::G_INTRINSIC_TRUNC:
504 case TargetOpcode::G_INTRINSIC_ROUND:
506 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
508 case TargetOpcode::G_INTRINSIC_LRINT:
510 case TargetOpcode::G_INTRINSIC_LLRINT:
530 AttributeList CallerAttrs =
F.getAttributes();
531 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
532 .removeAttribute(Attribute::NoAlias)
533 .removeAttribute(Attribute::NonNull)
538 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
539 CallerAttrs.hasRetAttr(Attribute::SExt))
550 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
557 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
565 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
568 if (Ret->getNumImplicitOperands() != 1)
571 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
595 Info.OrigRet = Result;
598 (Result.Ty->isVoidTy() ||
604 if (!CLI.lowerCall(MIRBuilder, Info))
607 if (
MI && Info.LoweredTailCall) {
608 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
618 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
619 "Expected instr following MI to be return or debug inst?");
622 Next->eraseFromParent();
623 }
while (
MI->getNextNode());
637 const char *Name = TLI.getLibcallName(
Libcall);
641 return createLibcall(MIRBuilder, Name, Result, Args, CC, LocObserver,
MI);
653 Args.push_back({MO.getReg(), OpType, 0});
655 {
MI.getOperand(0).getReg(), OpType, 0}, Args,
662 MachineFunction &MF = *
MI.getMF();
668 LLT DstTy = MRI.getType(DstSin);
673 unsigned AddrSpace =
DL.getAllocaAddrSpace();
674 MachinePointerInfo PtrInfo;
692 if (LibcallResult != LegalizeResult::Legalized)
700 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
701 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
702 MI.eraseFromParent();
717 LLT DstTy = MRI.getType(DstFrac);
722 unsigned AddrSpace =
DL.getAllocaAddrSpace();
723 MachinePointerInfo PtrInfo;
732 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
735 if (LibcallResult != LegalizeResult::Legalized)
741 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
742 MI.eraseFromParent();
754 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
758 LLT OpLLT =
MRI.getType(Reg);
759 Type *OpTy =
nullptr;
764 Args.push_back({Reg, OpTy, 0});
769 RTLIB::Libcall RTLibcall;
770 unsigned Opc =
MI.getOpcode();
773 case TargetOpcode::G_BZERO:
774 RTLibcall = RTLIB::BZERO;
775 Name = TLI.getLibcallName(RTLibcall);
777 case TargetOpcode::G_MEMCPY:
778 RTLibcall = RTLIB::MEMCPY;
779 Name = TLI.getLibcallImplName(TLI.getMemcpyImpl()).data();
780 Args[0].Flags[0].setReturned();
782 case TargetOpcode::G_MEMMOVE:
783 RTLibcall = RTLIB::MEMMOVE;
784 Name = TLI.getLibcallName(RTLibcall);
785 Args[0].Flags[0].setReturned();
787 case TargetOpcode::G_MEMSET:
788 RTLibcall = RTLIB::MEMSET;
789 Name = TLI.getLibcallName(RTLibcall);
790 Args[0].Flags[0].setReturned();
804 Info.
CallConv = TLI.getLibcallCallingConv(RTLibcall);
808 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
812 if (!CLI.lowerCall(MIRBuilder, Info))
815 if (Info.LoweredTailCall) {
816 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
826 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
827 "Expected instr following MI to be return or debug inst?");
830 Next->eraseFromParent();
831 }
while (
MI.getNextNode());
841 unsigned Opc =
MI.getOpcode();
843 auto &MMO = AtomicMI.getMMO();
844 auto Ordering = MMO.getMergedOrdering();
845 LLT MemType = MMO.getMemoryType();
848 return RTLIB::UNKNOWN_LIBCALL;
850#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
852 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
854 case TargetOpcode::G_ATOMIC_CMPXCHG:
855 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
856 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
857 return getOutlineAtomicHelper(LC, Ordering, MemSize);
859 case TargetOpcode::G_ATOMICRMW_XCHG: {
860 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
861 return getOutlineAtomicHelper(LC, Ordering, MemSize);
863 case TargetOpcode::G_ATOMICRMW_ADD:
864 case TargetOpcode::G_ATOMICRMW_SUB: {
865 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
866 return getOutlineAtomicHelper(LC, Ordering, MemSize);
868 case TargetOpcode::G_ATOMICRMW_AND: {
869 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
870 return getOutlineAtomicHelper(LC, Ordering, MemSize);
872 case TargetOpcode::G_ATOMICRMW_OR: {
873 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
874 return getOutlineAtomicHelper(LC, Ordering, MemSize);
876 case TargetOpcode::G_ATOMICRMW_XOR: {
877 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
878 return getOutlineAtomicHelper(LC, Ordering, MemSize);
881 return RTLIB::UNKNOWN_LIBCALL;
894 unsigned Opc =
MI.getOpcode();
896 case TargetOpcode::G_ATOMIC_CMPXCHG:
897 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
900 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
901 MI.getFirst4RegLLTs();
904 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
905 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
906 NewLLT) =
MI.getFirst5RegLLTs();
916 case TargetOpcode::G_ATOMICRMW_XCHG:
917 case TargetOpcode::G_ATOMICRMW_ADD:
918 case TargetOpcode::G_ATOMICRMW_SUB:
919 case TargetOpcode::G_ATOMICRMW_AND:
920 case TargetOpcode::G_ATOMICRMW_OR:
921 case TargetOpcode::G_ATOMICRMW_XOR: {
922 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
925 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
929 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
944 const char *Name = TLI.getLibcallName(RTLibcall);
954 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
959 if (!CLI.lowerCall(MIRBuilder,
Info))
971 case TargetOpcode::G_FPEXT:
973 case TargetOpcode::G_FPTRUNC:
975 case TargetOpcode::G_FPTOSI:
977 case TargetOpcode::G_FPTOUI:
979 case TargetOpcode::G_SITOFP:
981 case TargetOpcode::G_UITOFP:
992 if (FromType->isIntegerTy()) {
994 Arg.
Flags[0].setSExt();
996 Arg.
Flags[0].setZExt();
1001 {
MI.getOperand(0).getReg(), ToType, 0}, Arg, LocObserver,
1005static RTLIB::Libcall
1007 RTLIB::Libcall RTLibcall;
1008 switch (
MI.getOpcode()) {
1009 case TargetOpcode::G_GET_FPENV:
1010 RTLibcall = RTLIB::FEGETENV;
1012 case TargetOpcode::G_SET_FPENV:
1013 case TargetOpcode::G_RESET_FPENV:
1014 RTLibcall = RTLIB::FESETENV;
1016 case TargetOpcode::G_GET_FPMODE:
1017 RTLibcall = RTLIB::FEGETMODE;
1019 case TargetOpcode::G_SET_FPMODE:
1020 case TargetOpcode::G_RESET_FPMODE:
1021 RTLibcall = RTLIB::FESETMODE;
1054 LLT StateTy = MRI.getType(Dst);
1057 MachinePointerInfo TempPtrInfo;
1061 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1067 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1068 LocObserver,
nullptr);
1075 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1094 LLT StateTy = MRI.getType(Src);
1097 MachinePointerInfo TempPtrInfo;
1106 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1111 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1112 LocObserver,
nullptr);
1118static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1120#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1124 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1126 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1128 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1130 llvm_unreachable("unexpected size"); \
1162 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1165 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1172 LLT DstTy = MRI.getType(DstReg);
1173 const auto Cond =
Cmp->getCond();
1178 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1183 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1187 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1194 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1200 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1202 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1215 const auto [OeqLibcall, OeqPred] =
1217 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1219 const auto [UnoLibcall, UnoPred] =
1221 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1236 const auto [OeqLibcall, OeqPred] =
1241 const auto [UnoLibcall, UnoPred] =
1246 if (NotOeq && NotUno)
1265 const auto [InversedLibcall, InversedPred] =
1267 if (!BuildLibcall(InversedLibcall,
1293 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1295 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1298 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1304 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}),
1310 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1312 switch (
MI.getOpcode()) {
1315 case TargetOpcode::G_MUL:
1316 case TargetOpcode::G_SDIV:
1317 case TargetOpcode::G_UDIV:
1318 case TargetOpcode::G_SREM:
1319 case TargetOpcode::G_UREM:
1320 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1321 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1329 case TargetOpcode::G_FADD:
1330 case TargetOpcode::G_FSUB:
1331 case TargetOpcode::G_FMUL:
1332 case TargetOpcode::G_FDIV:
1333 case TargetOpcode::G_FMA:
1334 case TargetOpcode::G_FPOW:
1335 case TargetOpcode::G_FREM:
1336 case TargetOpcode::G_FCOS:
1337 case TargetOpcode::G_FSIN:
1338 case TargetOpcode::G_FTAN:
1339 case TargetOpcode::G_FACOS:
1340 case TargetOpcode::G_FASIN:
1341 case TargetOpcode::G_FATAN:
1342 case TargetOpcode::G_FATAN2:
1343 case TargetOpcode::G_FCOSH:
1344 case TargetOpcode::G_FSINH:
1345 case TargetOpcode::G_FTANH:
1346 case TargetOpcode::G_FLOG10:
1347 case TargetOpcode::G_FLOG:
1348 case TargetOpcode::G_FLOG2:
1349 case TargetOpcode::G_FEXP:
1350 case TargetOpcode::G_FEXP2:
1351 case TargetOpcode::G_FEXP10:
1352 case TargetOpcode::G_FCEIL:
1353 case TargetOpcode::G_FFLOOR:
1354 case TargetOpcode::G_FMINNUM:
1355 case TargetOpcode::G_FMAXNUM:
1356 case TargetOpcode::G_FMINIMUMNUM:
1357 case TargetOpcode::G_FMAXIMUMNUM:
1358 case TargetOpcode::G_FSQRT:
1359 case TargetOpcode::G_FRINT:
1360 case TargetOpcode::G_FNEARBYINT:
1361 case TargetOpcode::G_INTRINSIC_TRUNC:
1362 case TargetOpcode::G_INTRINSIC_ROUND:
1363 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1364 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1368 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1376 case TargetOpcode::G_FSINCOS: {
1377 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1381 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1386 case TargetOpcode::G_FMODF: {
1387 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1391 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1396 case TargetOpcode::G_LROUND:
1397 case TargetOpcode::G_LLROUND:
1398 case TargetOpcode::G_INTRINSIC_LRINT:
1399 case TargetOpcode::G_INTRINSIC_LLRINT: {
1400 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1404 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1406 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1412 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1415 MI.eraseFromParent();
1418 case TargetOpcode::G_FPOWI:
1419 case TargetOpcode::G_FLDEXP: {
1420 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1424 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1426 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1431 {
MI.getOperand(1).getReg(), HLTy, 0},
1432 {
MI.getOperand(2).getReg(), ITy, 1}};
1433 Args[1].Flags[0].setSExt();
1436 Args, LocObserver, &
MI);
1441 case TargetOpcode::G_FPEXT:
1442 case TargetOpcode::G_FPTRUNC: {
1445 if (!FromTy || !ToTy)
1453 case TargetOpcode::G_FCMP: {
1457 MI.eraseFromParent();
1460 case TargetOpcode::G_FPTOSI:
1461 case TargetOpcode::G_FPTOUI: {
1465 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1466 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1474 case TargetOpcode::G_SITOFP:
1475 case TargetOpcode::G_UITOFP: {
1476 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1479 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1481 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1484 LocObserver, TLI, IsSigned);
1489 case TargetOpcode::G_ATOMICRMW_XCHG:
1490 case TargetOpcode::G_ATOMICRMW_ADD:
1491 case TargetOpcode::G_ATOMICRMW_SUB:
1492 case TargetOpcode::G_ATOMICRMW_AND:
1493 case TargetOpcode::G_ATOMICRMW_OR:
1494 case TargetOpcode::G_ATOMICRMW_XOR:
1495 case TargetOpcode::G_ATOMIC_CMPXCHG:
1496 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1502 case TargetOpcode::G_BZERO:
1503 case TargetOpcode::G_MEMCPY:
1504 case TargetOpcode::G_MEMMOVE:
1505 case TargetOpcode::G_MEMSET: {
1510 MI.eraseFromParent();
1513 case TargetOpcode::G_GET_FPENV:
1514 case TargetOpcode::G_GET_FPMODE: {
1520 case TargetOpcode::G_SET_FPENV:
1521 case TargetOpcode::G_SET_FPMODE: {
1527 case TargetOpcode::G_RESET_FPENV:
1528 case TargetOpcode::G_RESET_FPMODE: {
1537 MI.eraseFromParent();
1544 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1547 switch (
MI.getOpcode()) {
1550 case TargetOpcode::G_IMPLICIT_DEF: {
1552 LLT DstTy = MRI.getType(DstReg);
1560 if (SizeOp0 % NarrowSize != 0) {
1561 LLT ImplicitTy = NarrowTy;
1568 MI.eraseFromParent();
1572 int NumParts = SizeOp0 / NarrowSize;
1575 for (
int i = 0; i < NumParts; ++i)
1579 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1581 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1582 MI.eraseFromParent();
1585 case TargetOpcode::G_CONSTANT: {
1586 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1587 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1588 unsigned TotalSize = Ty.getSizeInBits();
1590 int NumParts = TotalSize / NarrowSize;
1593 for (
int I = 0;
I != NumParts; ++
I) {
1594 unsigned Offset =
I * NarrowSize;
1601 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1603 if (LeftoverBits != 0) {
1607 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1611 insertParts(
MI.getOperand(0).getReg(),
1612 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1614 MI.eraseFromParent();
1617 case TargetOpcode::G_SEXT:
1618 case TargetOpcode::G_ZEXT:
1619 case TargetOpcode::G_ANYEXT:
1621 case TargetOpcode::G_TRUNC: {
1625 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1627 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1631 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1632 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1633 MI.eraseFromParent();
1636 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1637 case TargetOpcode::G_FREEZE: {
1641 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1646 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1648 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1650 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1654 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1655 MI.eraseFromParent();
1658 case TargetOpcode::G_ADD:
1659 case TargetOpcode::G_SUB:
1660 case TargetOpcode::G_SADDO:
1661 case TargetOpcode::G_SSUBO:
1662 case TargetOpcode::G_SADDE:
1663 case TargetOpcode::G_SSUBE:
1664 case TargetOpcode::G_UADDO:
1665 case TargetOpcode::G_USUBO:
1666 case TargetOpcode::G_UADDE:
1667 case TargetOpcode::G_USUBE:
1669 case TargetOpcode::G_MUL:
1670 case TargetOpcode::G_UMULH:
1672 case TargetOpcode::G_EXTRACT:
1674 case TargetOpcode::G_INSERT:
1676 case TargetOpcode::G_LOAD: {
1678 Register DstReg = LoadMI.getDstReg();
1679 LLT DstTy = MRI.getType(DstReg);
1683 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1684 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1685 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1687 LoadMI.eraseFromParent();
1693 case TargetOpcode::G_ZEXTLOAD:
1694 case TargetOpcode::G_SEXTLOAD: {
1696 Register DstReg = LoadMI.getDstReg();
1697 Register PtrReg = LoadMI.getPointerReg();
1699 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1700 auto &MMO = LoadMI.getMMO();
1703 if (MemSize == NarrowSize) {
1705 }
else if (MemSize < NarrowSize) {
1706 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1707 }
else if (MemSize > NarrowSize) {
1717 LoadMI.eraseFromParent();
1720 case TargetOpcode::G_STORE: {
1723 Register SrcReg = StoreMI.getValueReg();
1724 LLT SrcTy = MRI.getType(SrcReg);
1725 if (SrcTy.isVector())
1728 int NumParts = SizeOp0 / NarrowSize;
1730 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1731 if (SrcTy.isVector() && LeftoverBits != 0)
1734 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1735 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1737 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1738 StoreMI.eraseFromParent();
1744 case TargetOpcode::G_SELECT:
1746 case TargetOpcode::G_AND:
1747 case TargetOpcode::G_OR:
1748 case TargetOpcode::G_XOR: {
1760 case TargetOpcode::G_SHL:
1761 case TargetOpcode::G_LSHR:
1762 case TargetOpcode::G_ASHR:
1764 case TargetOpcode::G_CTLZ:
1765 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1766 case TargetOpcode::G_CTTZ:
1767 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1768 case TargetOpcode::G_CTPOP:
1770 switch (
MI.getOpcode()) {
1771 case TargetOpcode::G_CTLZ:
1772 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1774 case TargetOpcode::G_CTTZ:
1775 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1777 case TargetOpcode::G_CTPOP:
1787 case TargetOpcode::G_INTTOPTR:
1795 case TargetOpcode::G_PTRTOINT:
1803 case TargetOpcode::G_PHI: {
1806 if (SizeOp0 % NarrowSize != 0)
1809 unsigned NumParts = SizeOp0 / NarrowSize;
1813 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1821 for (
unsigned i = 0; i < NumParts; ++i) {
1822 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1824 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1825 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1826 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1829 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1831 MI.eraseFromParent();
1834 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1835 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1839 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1845 case TargetOpcode::G_ICMP: {
1847 LLT SrcTy = MRI.getType(LHS);
1853 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1859 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1860 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1866 LLT ResTy = MRI.getType(Dst);
1871 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1873 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1874 auto LHS = std::get<0>(LHSAndRHS);
1875 auto RHS = std::get<1>(LHSAndRHS);
1876 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1883 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1884 auto LHS = std::get<0>(LHSAndRHS);
1885 auto RHS = std::get<1>(LHSAndRHS);
1886 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1887 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1888 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1889 TargetOpcode::G_ZEXT);
1896 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1897 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1898 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1903 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1907 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1912 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1916 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1919 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1922 LHSPartRegs[
I], RHSPartRegs[
I]);
1923 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1929 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1933 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1938 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1942 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1943 RHSLeftoverRegs[
I]);
1945 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1946 RHSLeftoverRegs[
I]);
1949 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1950 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1956 MI.eraseFromParent();
1959 case TargetOpcode::G_FCMP:
1968 case TargetOpcode::G_SEXT_INREG: {
1972 int64_t SizeInBits =
MI.getOperand(2).getImm();
1981 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
1982 MO1.
setReg(TruncMIB.getReg(0));
1985 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
1997 if (SizeOp0 % NarrowSize != 0)
1999 int NumParts = SizeOp0 / NarrowSize;
2007 for (
int i = 0; i < NumParts; ++i) {
2008 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2023 for (
int i = 0; i < NumParts; ++i) {
2026 PartialExtensionReg = DstRegs.
back();
2028 assert(PartialExtensionReg &&
2029 "Expected to visit partial extension before full");
2030 if (FullExtensionReg) {
2035 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2037 FullExtensionReg = DstRegs.
back();
2042 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2045 PartialExtensionReg = DstRegs.
back();
2051 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2052 MI.eraseFromParent();
2055 case TargetOpcode::G_BSWAP:
2056 case TargetOpcode::G_BITREVERSE: {
2057 if (SizeOp0 % NarrowSize != 0)
2062 unsigned NumParts = SizeOp0 / NarrowSize;
2063 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2066 for (
unsigned i = 0; i < NumParts; ++i) {
2067 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2068 {SrcRegs[NumParts - 1 - i]});
2072 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2075 MI.eraseFromParent();
2078 case TargetOpcode::G_PTR_ADD:
2079 case TargetOpcode::G_PTRMASK: {
2087 case TargetOpcode::G_FPTOUI:
2088 case TargetOpcode::G_FPTOSI:
2089 case TargetOpcode::G_FPTOUI_SAT:
2090 case TargetOpcode::G_FPTOSI_SAT:
2092 case TargetOpcode::G_FPEXT:
2099 case TargetOpcode::G_FLDEXP:
2100 case TargetOpcode::G_STRICT_FLDEXP:
2102 case TargetOpcode::G_VSCALE: {
2104 LLT Ty = MRI.getType(Dst);
2108 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2109 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2110 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2113 MI.eraseFromParent();
2120 LLT Ty = MRI.getType(Val);
2126 if (Ty.isPointer()) {
2127 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2129 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2135 if (Ty.isPointerVector())
2136 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2137 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2141 unsigned OpIdx,
unsigned ExtOpcode) {
2143 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2144 MO.
setReg(ExtB.getReg(0));
2150 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2151 MO.
setReg(ExtB.getReg(0));
2155 unsigned OpIdx,
unsigned TruncOpcode) {
2157 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2159 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2164 unsigned OpIdx,
unsigned ExtOpcode) {
2166 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2168 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2177 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2179 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2185 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2195 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2202LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2207 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2208 if (DstTy.isVector())
2211 LLT SrcTy =
MRI.getType(Src1Reg);
2212 const int DstSize = DstTy.getSizeInBits();
2213 const int SrcSize = SrcTy.getSizeInBits();
2215 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2217 unsigned NumOps =
MI.getNumOperands();
2218 unsigned NumSrc =
MI.getNumOperands() - 1;
2219 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2221 if (WideSize >= DstSize) {
2225 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2226 const unsigned Offset = (
I - 1) * PartSize;
2234 MRI.createGenericVirtualRegister(WideTy);
2239 ResultReg = NextResult;
2242 if (WideSize > DstSize)
2244 else if (DstTy.isPointer())
2247 MI.eraseFromParent();
2272 const int GCD = std::gcd(SrcSize, WideSize);
2282 if (GCD == SrcSize) {
2285 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2286 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2292 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2294 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2298 const int PartsPerGCD = WideSize / GCD;
2302 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2304 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2311 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2313 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2314 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2317 MI.eraseFromParent();
2322LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2327 int NumDst =
MI.getNumOperands() - 1;
2328 Register SrcReg =
MI.getOperand(NumDst).getReg();
2329 LLT SrcTy = MRI.getType(SrcReg);
2333 Register Dst0Reg =
MI.getOperand(0).getReg();
2334 LLT DstTy = MRI.getType(Dst0Reg);
2343 dbgs() <<
"Not casting non-integral address space integer\n");
2348 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2356 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2364 for (
int I = 1;
I != NumDst; ++
I) {
2365 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2366 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2370 MI.eraseFromParent();
2381 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2385 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2388 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2406 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2411 if (PartsPerRemerge == 1) {
2414 for (
int I = 0;
I != NumUnmerge; ++
I) {
2415 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2417 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2418 int Idx =
I * PartsPerUnmerge + J;
2420 MIB.addDef(
MI.getOperand(Idx).getReg());
2423 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2427 MIB.addUse(Unmerge.getReg(
I));
2430 SmallVector<Register, 16> Parts;
2431 for (
int J = 0; J != NumUnmerge; ++J)
2432 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2435 for (
int I = 0;
I != NumDst; ++
I) {
2436 for (
int J = 0; J < PartsPerRemerge; ++J) {
2437 const int Idx =
I * PartsPerRemerge + J;
2441 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2442 RemergeParts.
clear();
2446 MI.eraseFromParent();
2451LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2453 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2454 unsigned Offset =
MI.getOperand(2).getImm();
2457 if (SrcTy.
isVector() || DstTy.isVector())
2469 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2473 if (DstTy.isPointer())
2480 MI.eraseFromParent();
2485 LLT ShiftTy = SrcTy;
2494 MI.eraseFromParent();
2525LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2527 if (TypeIdx != 0 || WideTy.
isVector())
2537LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2541 std::optional<Register> CarryIn;
2542 switch (
MI.getOpcode()) {
2545 case TargetOpcode::G_SADDO:
2546 Opcode = TargetOpcode::G_ADD;
2547 ExtOpcode = TargetOpcode::G_SEXT;
2549 case TargetOpcode::G_SSUBO:
2550 Opcode = TargetOpcode::G_SUB;
2551 ExtOpcode = TargetOpcode::G_SEXT;
2553 case TargetOpcode::G_UADDO:
2554 Opcode = TargetOpcode::G_ADD;
2555 ExtOpcode = TargetOpcode::G_ZEXT;
2557 case TargetOpcode::G_USUBO:
2558 Opcode = TargetOpcode::G_SUB;
2559 ExtOpcode = TargetOpcode::G_ZEXT;
2561 case TargetOpcode::G_SADDE:
2562 Opcode = TargetOpcode::G_UADDE;
2563 ExtOpcode = TargetOpcode::G_SEXT;
2564 CarryIn =
MI.getOperand(4).getReg();
2566 case TargetOpcode::G_SSUBE:
2567 Opcode = TargetOpcode::G_USUBE;
2568 ExtOpcode = TargetOpcode::G_SEXT;
2569 CarryIn =
MI.getOperand(4).getReg();
2571 case TargetOpcode::G_UADDE:
2572 Opcode = TargetOpcode::G_UADDE;
2573 ExtOpcode = TargetOpcode::G_ZEXT;
2574 CarryIn =
MI.getOperand(4).getReg();
2576 case TargetOpcode::G_USUBE:
2577 Opcode = TargetOpcode::G_USUBE;
2578 ExtOpcode = TargetOpcode::G_ZEXT;
2579 CarryIn =
MI.getOperand(4).getReg();
2595 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2596 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2600 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2602 .buildInstr(Opcode, {WideTy, CarryOutTy},
2603 {LHSExt, RHSExt, *CarryIn})
2606 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2608 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2609 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2610 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2615 MI.eraseFromParent();
2620LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2622 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2623 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2624 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2625 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2626 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2639 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2646 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2650 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2651 {ShiftL, ShiftR},
MI.getFlags());
2656 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2659 MI.eraseFromParent();
2664LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2673 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2675 LLT SrcTy = MRI.getType(
LHS);
2676 LLT OverflowTy = MRI.getType(OriginalOverflow);
2683 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2684 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2685 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2692 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2694 MachineInstrBuilder Mulo;
2695 if (WideMulCanOverflow)
2696 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2697 {LeftOperand, RightOperand});
2699 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2704 MachineInstrBuilder ExtResult;
2711 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2715 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2718 if (WideMulCanOverflow) {
2726 MI.eraseFromParent();
2732 unsigned Opcode =
MI.getOpcode();
2736 case TargetOpcode::G_ATOMICRMW_XCHG:
2737 case TargetOpcode::G_ATOMICRMW_ADD:
2738 case TargetOpcode::G_ATOMICRMW_SUB:
2739 case TargetOpcode::G_ATOMICRMW_AND:
2740 case TargetOpcode::G_ATOMICRMW_OR:
2741 case TargetOpcode::G_ATOMICRMW_XOR:
2742 case TargetOpcode::G_ATOMICRMW_MIN:
2743 case TargetOpcode::G_ATOMICRMW_MAX:
2744 case TargetOpcode::G_ATOMICRMW_UMIN:
2745 case TargetOpcode::G_ATOMICRMW_UMAX:
2746 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2752 case TargetOpcode::G_ATOMIC_CMPXCHG:
2753 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2760 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2770 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2775 case TargetOpcode::G_EXTRACT:
2776 return widenScalarExtract(
MI, TypeIdx, WideTy);
2777 case TargetOpcode::G_INSERT:
2778 return widenScalarInsert(
MI, TypeIdx, WideTy);
2779 case TargetOpcode::G_MERGE_VALUES:
2780 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2781 case TargetOpcode::G_UNMERGE_VALUES:
2782 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2783 case TargetOpcode::G_SADDO:
2784 case TargetOpcode::G_SSUBO:
2785 case TargetOpcode::G_UADDO:
2786 case TargetOpcode::G_USUBO:
2787 case TargetOpcode::G_SADDE:
2788 case TargetOpcode::G_SSUBE:
2789 case TargetOpcode::G_UADDE:
2790 case TargetOpcode::G_USUBE:
2791 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2792 case TargetOpcode::G_UMULO:
2793 case TargetOpcode::G_SMULO:
2794 return widenScalarMulo(
MI, TypeIdx, WideTy);
2795 case TargetOpcode::G_SADDSAT:
2796 case TargetOpcode::G_SSUBSAT:
2797 case TargetOpcode::G_SSHLSAT:
2798 case TargetOpcode::G_UADDSAT:
2799 case TargetOpcode::G_USUBSAT:
2800 case TargetOpcode::G_USHLSAT:
2801 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2802 case TargetOpcode::G_CTTZ:
2803 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2804 case TargetOpcode::G_CTLZ:
2805 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
2806 case TargetOpcode::G_CTPOP: {
2817 unsigned ExtOpc = Opcode == TargetOpcode::G_CTTZ ||
2818 Opcode == TargetOpcode::G_CTTZ_ZERO_UNDEF
2819 ? TargetOpcode::G_ANYEXT
2820 : TargetOpcode::G_ZEXT;
2821 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2822 LLT CurTy = MRI.getType(SrcReg);
2823 unsigned NewOpc = Opcode;
2824 if (NewOpc == TargetOpcode::G_CTTZ) {
2831 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2833 NewOpc = TargetOpcode::G_CTTZ_ZERO_UNDEF;
2838 if (Opcode == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
2848 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2850 if (Opcode == TargetOpcode::G_CTLZ) {
2853 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff));
2856 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2857 MI.eraseFromParent();
2860 case TargetOpcode::G_BSWAP: {
2864 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2865 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2866 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2869 MI.getOperand(0).setReg(DstExt);
2873 LLT Ty = MRI.getType(DstReg);
2875 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2876 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2882 case TargetOpcode::G_BITREVERSE: {
2886 LLT Ty = MRI.getType(DstReg);
2889 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2891 MI.getOperand(0).setReg(DstExt);
2894 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2895 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2900 case TargetOpcode::G_FREEZE:
2901 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2908 case TargetOpcode::G_ABS:
2915 case TargetOpcode::G_ADD:
2916 case TargetOpcode::G_AND:
2917 case TargetOpcode::G_MUL:
2918 case TargetOpcode::G_OR:
2919 case TargetOpcode::G_XOR:
2920 case TargetOpcode::G_SUB:
2921 case TargetOpcode::G_SHUFFLE_VECTOR:
2932 case TargetOpcode::G_SBFX:
2933 case TargetOpcode::G_UBFX:
2947 case TargetOpcode::G_SHL:
2963 case TargetOpcode::G_ROTR:
2964 case TargetOpcode::G_ROTL:
2973 case TargetOpcode::G_SDIV:
2974 case TargetOpcode::G_SREM:
2975 case TargetOpcode::G_SMIN:
2976 case TargetOpcode::G_SMAX:
2977 case TargetOpcode::G_ABDS:
2985 case TargetOpcode::G_SDIVREM:
2995 case TargetOpcode::G_ASHR:
2996 case TargetOpcode::G_LSHR:
3000 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3001 : TargetOpcode::G_ZEXT;
3014 case TargetOpcode::G_UDIV:
3015 case TargetOpcode::G_UREM:
3016 case TargetOpcode::G_ABDU:
3023 case TargetOpcode::G_UDIVREM:
3032 case TargetOpcode::G_UMIN:
3033 case TargetOpcode::G_UMAX: {
3034 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3036 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3040 ? TargetOpcode::G_SEXT
3041 : TargetOpcode::G_ZEXT;
3051 case TargetOpcode::G_SELECT:
3061 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3068 case TargetOpcode::G_FPEXT:
3076 case TargetOpcode::G_FPTOSI:
3077 case TargetOpcode::G_FPTOUI:
3078 case TargetOpcode::G_INTRINSIC_LRINT:
3079 case TargetOpcode::G_INTRINSIC_LLRINT:
3080 case TargetOpcode::G_IS_FPCLASS:
3090 case TargetOpcode::G_SITOFP:
3100 case TargetOpcode::G_UITOFP:
3110 case TargetOpcode::G_FPTOSI_SAT:
3111 case TargetOpcode::G_FPTOUI_SAT:
3116 LLT Ty = MRI.getType(OldDst);
3117 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3119 MI.getOperand(0).setReg(ExtReg);
3120 uint64_t ShortBits = Ty.getScalarSizeInBits();
3123 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3134 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3135 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3143 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3151 case TargetOpcode::G_LOAD:
3152 case TargetOpcode::G_SEXTLOAD:
3153 case TargetOpcode::G_ZEXTLOAD:
3159 case TargetOpcode::G_STORE: {
3163 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3164 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3165 if (!Ty.isScalar()) {
3173 MI.setMemRefs(MF, {NewMMO});
3180 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3181 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3187 case TargetOpcode::G_CONSTANT: {
3190 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3191 MRI.getType(
MI.getOperand(0).getReg()));
3192 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3193 ExtOpc == TargetOpcode::G_ANYEXT) &&
3196 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3200 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3206 case TargetOpcode::G_FCONSTANT: {
3212 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3214 MI.eraseFromParent();
3217 case TargetOpcode::G_IMPLICIT_DEF: {
3223 case TargetOpcode::G_BRCOND:
3229 case TargetOpcode::G_FCMP:
3240 case TargetOpcode::G_ICMP:
3245 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3249 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3250 unsigned ExtOpcode =
3254 ? TargetOpcode::G_SEXT
3255 : TargetOpcode::G_ZEXT;
3262 case TargetOpcode::G_PTR_ADD:
3263 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3269 case TargetOpcode::G_PHI: {
3270 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3273 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3285 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3288 LLT VecTy = MRI.getType(VecReg);
3293 TargetOpcode::G_ANYEXT);
3307 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3323 LLT VecTy = MRI.getType(VecReg);
3342 case TargetOpcode::G_FADD:
3343 case TargetOpcode::G_FMUL:
3344 case TargetOpcode::G_FSUB:
3345 case TargetOpcode::G_FMA:
3346 case TargetOpcode::G_FMAD:
3347 case TargetOpcode::G_FNEG:
3348 case TargetOpcode::G_FABS:
3349 case TargetOpcode::G_FCANONICALIZE:
3350 case TargetOpcode::G_FMINNUM:
3351 case TargetOpcode::G_FMAXNUM:
3352 case TargetOpcode::G_FMINNUM_IEEE:
3353 case TargetOpcode::G_FMAXNUM_IEEE:
3354 case TargetOpcode::G_FMINIMUM:
3355 case TargetOpcode::G_FMAXIMUM:
3356 case TargetOpcode::G_FMINIMUMNUM:
3357 case TargetOpcode::G_FMAXIMUMNUM:
3358 case TargetOpcode::G_FDIV:
3359 case TargetOpcode::G_FREM:
3360 case TargetOpcode::G_FCEIL:
3361 case TargetOpcode::G_FFLOOR:
3362 case TargetOpcode::G_FCOS:
3363 case TargetOpcode::G_FSIN:
3364 case TargetOpcode::G_FTAN:
3365 case TargetOpcode::G_FACOS:
3366 case TargetOpcode::G_FASIN:
3367 case TargetOpcode::G_FATAN:
3368 case TargetOpcode::G_FATAN2:
3369 case TargetOpcode::G_FCOSH:
3370 case TargetOpcode::G_FSINH:
3371 case TargetOpcode::G_FTANH:
3372 case TargetOpcode::G_FLOG10:
3373 case TargetOpcode::G_FLOG:
3374 case TargetOpcode::G_FLOG2:
3375 case TargetOpcode::G_FRINT:
3376 case TargetOpcode::G_FNEARBYINT:
3377 case TargetOpcode::G_FSQRT:
3378 case TargetOpcode::G_FEXP:
3379 case TargetOpcode::G_FEXP2:
3380 case TargetOpcode::G_FEXP10:
3381 case TargetOpcode::G_FPOW:
3382 case TargetOpcode::G_INTRINSIC_TRUNC:
3383 case TargetOpcode::G_INTRINSIC_ROUND:
3384 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3388 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3394 case TargetOpcode::G_FMODF: {
3404 case TargetOpcode::G_FPOWI:
3405 case TargetOpcode::G_FLDEXP:
3406 case TargetOpcode::G_STRICT_FLDEXP: {
3408 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3429 case TargetOpcode::G_FFREXP: {
3442 case TargetOpcode::G_LROUND:
3443 case TargetOpcode::G_LLROUND:
3454 case TargetOpcode::G_INTTOPTR:
3462 case TargetOpcode::G_PTRTOINT:
3470 case TargetOpcode::G_BUILD_VECTOR: {
3474 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3480 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3488 case TargetOpcode::G_SEXT_INREG:
3497 case TargetOpcode::G_PTRMASK: {
3505 case TargetOpcode::G_VECREDUCE_ADD: {
3514 case TargetOpcode::G_VECREDUCE_FADD:
3515 case TargetOpcode::G_VECREDUCE_FMUL:
3516 case TargetOpcode::G_VECREDUCE_FMIN:
3517 case TargetOpcode::G_VECREDUCE_FMAX:
3518 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3519 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3524 LLT VecTy = MRI.getType(VecReg);
3533 case TargetOpcode::G_VSCALE: {
3540 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3545 case TargetOpcode::G_SPLAT_VECTOR: {
3554 case TargetOpcode::G_INSERT_SUBVECTOR: {
3562 LLT SubVecTy = MRI.getType(SubVec);
3566 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3567 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3568 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3572 auto SplatZero =
MIRBuilder.buildSplatVector(
3577 MI.eraseFromParent();
3586 auto Unmerge =
B.buildUnmerge(Ty, Src);
3587 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3596 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3598 LLT DstLLT =
MRI.getType(DstReg);
3610 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3619 MI.eraseFromParent();
3630 MI.eraseFromParent();
3637 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3638 if (SrcTy.isVector()) {
3642 if (DstTy.isVector()) {
3643 int NumDstElt = DstTy.getNumElements();
3644 int NumSrcElt = SrcTy.getNumElements();
3647 LLT DstCastTy = DstEltTy;
3648 LLT SrcPartTy = SrcEltTy;
3652 if (NumSrcElt < NumDstElt) {
3662 SrcPartTy = SrcEltTy;
3663 }
else if (NumSrcElt > NumDstElt) {
3674 DstCastTy = DstEltTy;
3679 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3683 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3684 MI.eraseFromParent();
3688 if (DstTy.isVector()) {
3691 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3692 MI.eraseFromParent();
3708 unsigned NewEltSize,
3709 unsigned OldEltSize) {
3710 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3711 LLT IdxTy =
B.getMRI()->getType(Idx);
3714 auto OffsetMask =
B.buildConstant(
3716 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3717 return B.buildShl(IdxTy, OffsetIdx,
3718 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3733 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3737 unsigned OldNumElts = SrcVecTy.getNumElements();
3744 if (NewNumElts > OldNumElts) {
3755 if (NewNumElts % OldNumElts != 0)
3759 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3763 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3766 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3768 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3769 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3770 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3771 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3772 NewOps[
I] = Elt.getReg(0);
3775 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3777 MI.eraseFromParent();
3781 if (NewNumElts < OldNumElts) {
3782 if (NewEltSize % OldEltSize != 0)
3804 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3805 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3808 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3812 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3813 ScaledIdx).getReg(0);
3821 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3823 MI.eraseFromParent();
3837 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3838 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3839 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3840 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3843 auto EltMask =
B.buildConstant(
3847 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3848 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3851 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3855 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3869 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3870 MI.getFirst4RegLLTs();
3882 if (NewNumElts < OldNumElts) {
3883 if (NewEltSize % OldEltSize != 0)
3892 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3893 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3896 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3900 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3901 ScaledIdx).getReg(0);
3911 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3912 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3916 MI.eraseFromParent();
3946 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3950 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3951 return UnableToLegalize;
3956 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3958 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3967 MI.eraseFromParent();
3985 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3986 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3996 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3997 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3999 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4000 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4002 MI.eraseFromParent();
4032 LLT DstTy = MRI.getType(Dst);
4033 LLT SrcTy = MRI.getType(Src);
4039 if (DstTy == CastTy)
4047 if (CastEltSize < DstEltSize)
4050 auto AdjustAmt = CastEltSize / DstEltSize;
4051 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4052 SrcTyMinElts % AdjustAmt != 0)
4057 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4058 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4061 ES->eraseFromParent();
4096 LLT DstTy = MRI.getType(Dst);
4097 LLT BigVecTy = MRI.getType(BigVec);
4098 LLT SubVecTy = MRI.getType(SubVec);
4100 if (DstTy == CastTy)
4115 if (CastEltSize < DstEltSize)
4118 auto AdjustAmt = CastEltSize / DstEltSize;
4119 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4120 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4126 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4127 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4129 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4132 ES->eraseFromParent();
4140 LLT DstTy = MRI.getType(DstReg);
4148 if (MemSizeInBits != MemStoreSizeInBits) {
4165 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4169 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4170 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4172 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4175 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4177 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4180 if (DstTy != LoadTy)
4188 if (
MIRBuilder.getDataLayout().isBigEndian())
4206 uint64_t LargeSplitSize, SmallSplitSize;
4211 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4218 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4221 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4232 if (Alignment.
value() * 8 > MemSizeInBits &&
4237 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4254 LLT PtrTy = MRI.getType(PtrReg);
4257 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4261 LargeSplitSize / 8);
4262 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4263 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4265 SmallPtr, *SmallMMO);
4267 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4268 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4270 if (AnyExtTy == DstTy)
4271 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4273 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4277 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4297 LLT SrcTy = MRI.getType(SrcReg);
4305 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4311 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4313 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4317 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4321 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4336 uint64_t LargeSplitSize, SmallSplitSize;
4343 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4346 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4355 if (SrcTy.isPointer()) {
4357 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4360 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4363 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4364 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4367 LLT PtrTy = MRI.getType(PtrReg);
4370 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4376 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4377 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4386 LLT SrcTy = MRI.getType(SrcReg);
4392 assert(SrcTy.isVector() &&
"Expect a vector store type");
4399 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4403 auto Elt =
MIRBuilder.buildExtractVectorElement(
4404 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4405 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4406 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4412 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4413 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4417 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4428 switch (
MI.getOpcode()) {
4429 case TargetOpcode::G_LOAD: {
4447 case TargetOpcode::G_STORE: {
4463 case TargetOpcode::G_SELECT: {
4467 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4469 dbgs() <<
"bitcast action not implemented for vector select\n");
4480 case TargetOpcode::G_AND:
4481 case TargetOpcode::G_OR:
4482 case TargetOpcode::G_XOR: {
4490 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4492 case TargetOpcode::G_INSERT_VECTOR_ELT:
4494 case TargetOpcode::G_CONCAT_VECTORS:
4496 case TargetOpcode::G_SHUFFLE_VECTOR:
4498 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4500 case TargetOpcode::G_INSERT_SUBVECTOR:
4508void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4518 switch(
MI.getOpcode()) {
4521 case TargetOpcode::G_FCONSTANT:
4523 case TargetOpcode::G_BITCAST:
4525 case TargetOpcode::G_SREM:
4526 case TargetOpcode::G_UREM: {
4527 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4529 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4530 {MI.getOperand(1), MI.getOperand(2)});
4532 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4534 MI.eraseFromParent();
4537 case TargetOpcode::G_SADDO:
4538 case TargetOpcode::G_SSUBO:
4540 case TargetOpcode::G_SADDE:
4542 case TargetOpcode::G_SSUBE:
4544 case TargetOpcode::G_UMULH:
4545 case TargetOpcode::G_SMULH:
4547 case TargetOpcode::G_SMULO:
4548 case TargetOpcode::G_UMULO: {
4551 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4552 LLT Ty = MRI.getType(Res);
4554 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4555 ? TargetOpcode::G_SMULH
4556 : TargetOpcode::G_UMULH;
4560 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4561 MI.removeOperand(1);
4564 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4572 if (Opcode == TargetOpcode::G_SMULH) {
4573 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4574 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4581 case TargetOpcode::G_FNEG: {
4582 auto [Res, SubByReg] =
MI.getFirst2Regs();
4583 LLT Ty = MRI.getType(Res);
4587 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4588 MI.eraseFromParent();
4591 case TargetOpcode::G_FSUB:
4592 case TargetOpcode::G_STRICT_FSUB: {
4593 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4594 LLT Ty = MRI.getType(Res);
4599 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4600 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4604 MI.eraseFromParent();
4607 case TargetOpcode::G_FMAD:
4609 case TargetOpcode::G_FFLOOR:
4611 case TargetOpcode::G_LROUND:
4612 case TargetOpcode::G_LLROUND: {
4615 LLT SrcTy = MRI.getType(SrcReg);
4616 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4619 MI.eraseFromParent();
4622 case TargetOpcode::G_INTRINSIC_ROUND:
4624 case TargetOpcode::G_FRINT: {
4627 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4630 case TargetOpcode::G_INTRINSIC_LRINT:
4631 case TargetOpcode::G_INTRINSIC_LLRINT: {
4634 LLT SrcTy = MRI.getType(SrcReg);
4636 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4638 MI.eraseFromParent();
4641 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4642 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4643 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4644 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4645 **
MI.memoperands_begin());
4647 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4648 MI.eraseFromParent();
4651 case TargetOpcode::G_LOAD:
4652 case TargetOpcode::G_SEXTLOAD:
4653 case TargetOpcode::G_ZEXTLOAD:
4655 case TargetOpcode::G_STORE:
4657 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4658 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4659 case TargetOpcode::G_CTLZ:
4660 case TargetOpcode::G_CTTZ:
4661 case TargetOpcode::G_CTPOP:
4664 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4666 Register NewRes = MRI.cloneVirtualRegister(Res);
4673 MI.eraseFromParent();
4677 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4678 const LLT CondTy = MRI.getType(CarryOut);
4679 const LLT Ty = MRI.getType(Res);
4681 Register NewRes = MRI.cloneVirtualRegister(Res);
4684 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4690 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4691 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4698 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4703 MI.eraseFromParent();
4707 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4712 MI.eraseFromParent();
4716 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4717 const LLT CondTy = MRI.getType(BorrowOut);
4718 const LLT Ty = MRI.getType(Res);
4721 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4727 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4728 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4735 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4736 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4738 MI.eraseFromParent();
4774 case G_MERGE_VALUES:
4776 case G_UNMERGE_VALUES:
4778 case TargetOpcode::G_SEXT_INREG: {
4779 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4780 int64_t SizeInBits =
MI.getOperand(2).getImm();
4782 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4783 LLT DstTy = MRI.getType(DstReg);
4784 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4787 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4788 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4789 MI.eraseFromParent();
4792 case G_EXTRACT_VECTOR_ELT:
4793 case G_INSERT_VECTOR_ELT:
4795 case G_SHUFFLE_VECTOR:
4797 case G_VECTOR_COMPRESS:
4799 case G_DYN_STACKALLOC:
4803 case G_STACKRESTORE:
4813 case G_READ_REGISTER:
4814 case G_WRITE_REGISTER:
4821 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4822 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4828 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4833 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4844 bool IsSigned =
MI.getOpcode() == G_ABDS;
4845 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4846 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4847 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4871 case G_MEMCPY_INLINE:
4872 return lowerMemcpyInline(
MI);
4883 case G_ATOMICRMW_SUB: {
4884 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4885 const LLT ValTy = MRI.getType(Val);
4889 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4890 MI.eraseFromParent();
4913 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4917 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4923 Align StackTypeAlign =
4930 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4931 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4936 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4948 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4951 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4962 "Converting bits to bytes lost precision");
4968 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4969 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4971 if (IdxTy != MRI.getType(Index))
4972 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4977 LLT PtrTy = MRI.getType(VecPtr);
4978 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4986 std::initializer_list<unsigned> NonVecOpIndices) {
4987 if (
MI.getNumMemOperands() != 0)
4990 LLT VecTy =
MRI.getType(
MI.getReg(0));
5004 if (!Ty.isVector()) {
5010 if (Ty.getNumElements() != NumElts)
5025 assert(Ty.isVector() &&
"Expected vector type");
5028 int NumParts, NumLeftover;
5029 std::tie(NumParts, NumLeftover) =
5032 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5033 for (
int i = 0; i < NumParts; ++i) {
5038 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5047 for (
unsigned i = 0; i <
N; ++i) {
5049 Ops.push_back(
Op.getReg());
5050 else if (
Op.isImm())
5051 Ops.push_back(
Op.getImm());
5052 else if (
Op.isPredicate())
5074 std::initializer_list<unsigned> NonVecOpIndices) {
5076 "Non-compatible opcode or not specified non-vector operands");
5077 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5079 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5080 unsigned NumDefs =
MI.getNumDefs();
5088 for (
unsigned i = 0; i < NumDefs; ++i) {
5089 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5097 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5098 ++UseIdx, ++UseNo) {
5101 MI.getOperand(UseIdx));
5110 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5114 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5116 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5117 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5120 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5121 Uses.push_back(InputOpsPieces[InputNo][i]);
5124 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5125 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5130 for (
unsigned i = 0; i < NumDefs; ++i)
5131 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5133 for (
unsigned i = 0; i < NumDefs; ++i)
5134 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5137 MI.eraseFromParent();
5144 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5146 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5147 unsigned NumDefs =
MI.getNumDefs();
5151 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5156 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5157 UseIdx += 2, ++UseNo) {
5165 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5167 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5168 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5170 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5173 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5174 Phi.addUse(InputOpsPieces[j][i]);
5175 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5185 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5187 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5190 MI.eraseFromParent();
5198 const int NumDst =
MI.getNumOperands() - 1;
5199 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5200 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5201 LLT SrcTy = MRI.getType(SrcReg);
5203 if (TypeIdx != 1 || NarrowTy == DstTy)
5210 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5213 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5227 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5228 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5229 const int PartsPerUnmerge = NumDst / NumUnmerge;
5231 for (
int I = 0;
I != NumUnmerge; ++
I) {
5232 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5234 for (
int J = 0; J != PartsPerUnmerge; ++J)
5235 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5236 MIB.addUse(Unmerge.getReg(
I));
5239 MI.eraseFromParent();
5246 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5250 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5252 if (NarrowTy == SrcTy)
5260 assert(SrcTy.isVector() &&
"Expected vector types");
5262 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5276 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5277 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5278 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5284 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5285 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5286 ++i,
Offset += NumNarrowTyElts) {
5289 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5292 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5293 MI.eraseFromParent();
5297 assert(TypeIdx == 0 &&
"Bad type index");
5298 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5313 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5314 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5316 for (
unsigned i = 0; i < NumParts; ++i) {
5318 for (
unsigned j = 0; j < NumElts; ++j)
5319 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5321 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5324 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5325 MI.eraseFromParent();
5333 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5335 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5337 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5339 InsertVal =
MI.getOperand(2).getReg();
5341 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5342 LLT VecTy = MRI.getType(SrcVec);
5348 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5352 MI.eraseFromParent();
5361 SplitPieces[IdxVal] = InsertVal;
5362 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5364 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5368 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5371 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5372 TargetOpcode::G_ANYEXT);
5376 LLT IdxTy = MRI.getType(Idx);
5377 int64_t PartIdx = IdxVal / NewNumElts;
5379 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5382 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5385 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5386 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5387 VecParts[PartIdx] = InsertPart.getReg(0);
5391 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5393 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5397 MI.eraseFromParent();
5417 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5429 LLT ValTy = MRI.getType(ValReg);
5438 int NumLeftover = -1;
5444 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5446 NumParts = NarrowRegs.
size();
5447 NumLeftover = NarrowLeftoverRegs.
size();
5454 LLT PtrTy = MRI.getType(AddrReg);
5457 unsigned TotalSize = ValTy.getSizeInBits();
5464 auto MMO = LdStMI.
getMMO();
5466 unsigned NumParts,
unsigned Offset) ->
unsigned {
5469 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5471 unsigned ByteOffset =
Offset / 8;
5474 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5481 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5482 ValRegs.push_back(Dst);
5483 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5485 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5494 unsigned HandledOffset =
5495 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5499 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5502 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5503 LeftoverTy, NarrowLeftoverRegs);
5517 switch (
MI.getOpcode()) {
5518 case G_IMPLICIT_DEF:
5534 case G_FCANONICALIZE:
5551 case G_INTRINSIC_LRINT:
5552 case G_INTRINSIC_LLRINT:
5553 case G_INTRINSIC_ROUND:
5554 case G_INTRINSIC_ROUNDEVEN:
5557 case G_INTRINSIC_TRUNC:
5585 case G_FMINNUM_IEEE:
5586 case G_FMAXNUM_IEEE:
5608 case G_CTLZ_ZERO_UNDEF:
5610 case G_CTTZ_ZERO_UNDEF:
5626 case G_ADDRSPACE_CAST:
5639 case G_STRICT_FLDEXP:
5648 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5653 case G_UNMERGE_VALUES:
5655 case G_BUILD_VECTOR:
5656 assert(TypeIdx == 0 &&
"not a vector type index");
5658 case G_CONCAT_VECTORS:
5662 case G_EXTRACT_VECTOR_ELT:
5663 case G_INSERT_VECTOR_ELT:
5672 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5673 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5675 case G_SHUFFLE_VECTOR:
5681 case G_INTRINSIC_FPTRUNC_ROUND:
5691 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5692 "Not a bitcast operation");
5697 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5699 unsigned NewElemCount =
5702 if (NewElemCount == 1) {
5705 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5711 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5720 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5721 MI.eraseFromParent();
5727 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5731 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5732 MI.getFirst3RegLLTs();
5735 if (DstTy != Src1Ty)
5737 if (DstTy != Src2Ty)
5752 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5768 unsigned InputUsed[2] = {-1U, -1U};
5769 unsigned FirstMaskIdx =
High * NewElts;
5770 bool UseBuildVector =
false;
5771 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5773 int Idx = Mask[FirstMaskIdx + MaskOffset];
5778 if (
Input >= std::size(Inputs)) {
5785 Idx -=
Input * NewElts;
5789 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5790 if (InputUsed[OpNo] ==
Input) {
5793 }
else if (InputUsed[OpNo] == -1U) {
5795 InputUsed[OpNo] =
Input;
5800 if (OpNo >= std::size(InputUsed)) {
5803 UseBuildVector =
true;
5808 Ops.push_back(Idx + OpNo * NewElts);
5811 if (UseBuildVector) {
5816 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5818 int Idx = Mask[FirstMaskIdx + MaskOffset];
5823 if (
Input >= std::size(Inputs)) {
5830 Idx -=
Input * NewElts;
5834 .buildExtractVectorElement(
5835 EltTy, Inputs[
Input],
5841 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5842 }
else if (InputUsed[0] == -1U) {
5844 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5845 }
else if (NewElts == 1) {
5846 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
5848 Register Op0 = Inputs[InputUsed[0]];
5852 : Inputs[InputUsed[1]];
5854 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5861 MI.eraseFromParent();
5874 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5880 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5883 const unsigned NumParts =
5885 : SrcTy.getNumElements();
5889 if (DstTy != NarrowTy)
5895 unsigned NumPartsLeft = NumParts;
5896 while (NumPartsLeft > 1) {
5897 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5900 .buildInstr(ScalarOpc, {NarrowTy},
5901 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5904 SplitSrcs = PartialResults;
5905 PartialResults.
clear();
5906 NumPartsLeft = SplitSrcs.
size();
5910 MI.eraseFromParent();
5915 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5916 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5919 MI.eraseFromParent();
5923 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5925 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5933 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5936 Register Acc = PartialReductions[0];
5937 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5938 if (Part == NumParts - 1) {
5940 {Acc, PartialReductions[Part]});
5943 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5947 MI.eraseFromParent();
5953 unsigned int TypeIdx,
5955 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5956 MI.getFirst3RegLLTs();
5957 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5961 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5962 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5963 "Unexpected vecreduce opcode");
5964 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5965 ? TargetOpcode::G_FADD
5966 : TargetOpcode::G_FMUL;
5969 unsigned NumParts = SrcTy.getNumElements();
5972 for (
unsigned i = 0; i < NumParts; i++)
5973 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5977 MI.eraseFromParent();
5984 unsigned ScalarOpc) {
5992 while (SplitSrcs.
size() > 1) {
5994 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6002 SplitSrcs = std::move(PartialRdxs);
6006 MI.getOperand(1).setReg(SplitSrcs[0]);
6013 const LLT HalfTy,
const LLT AmtTy) {
6015 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6016 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6020 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6021 MI.eraseFromParent();
6027 unsigned VTBits = 2 * NVTBits;
6030 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6031 if (Amt.
ugt(VTBits)) {
6033 }
else if (Amt.
ugt(NVTBits)) {
6036 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6037 }
else if (Amt == NVTBits) {
6045 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6048 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6049 if (Amt.
ugt(VTBits)) {
6051 }
else if (Amt.
ugt(NVTBits)) {
6053 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6055 }
else if (Amt == NVTBits) {
6059 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6061 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6063 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6069 if (Amt.
ugt(VTBits)) {
6071 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6072 }
else if (Amt.
ugt(NVTBits)) {
6074 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6076 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6077 }
else if (Amt == NVTBits) {
6080 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6082 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6084 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6086 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6093 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6094 MI.eraseFromParent();
6110 LLT DstTy = MRI.getType(DstReg);
6115 LLT ShiftAmtTy = MRI.getType(Amt);
6117 if (DstEltSize % 2 != 0)
6133 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6144 const unsigned NewBitSize = DstEltSize / 2;
6156 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6158 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6159 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6162 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6163 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6165 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6170 switch (
MI.getOpcode()) {
6171 case TargetOpcode::G_SHL: {
6173 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6175 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6176 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6177 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6180 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6181 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6183 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6185 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6187 ResultRegs[0] =
Lo.getReg(0);
6188 ResultRegs[1] =
Hi.getReg(0);
6191 case TargetOpcode::G_LSHR:
6192 case TargetOpcode::G_ASHR: {
6194 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6196 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6197 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6198 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6202 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6205 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6206 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6208 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6212 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6214 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6216 ResultRegs[0] =
Lo.getReg(0);
6217 ResultRegs[1] =
Hi.getReg(0);
6224 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6225 MI.eraseFromParent();
6234 LLT TargetTy,
LLT ShiftAmtTy) {
6237 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6239 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6240 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6241 const bool NeedsInterWordShift = ShiftBits != 0;
6244 case TargetOpcode::G_SHL: {
6247 if (PartIdx < ShiftWords)
6250 unsigned SrcIdx = PartIdx - ShiftWords;
6251 if (!NeedsInterWordShift)
6252 return SrcParts[SrcIdx];
6257 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6261 return Hi.getReg(0);
6264 case TargetOpcode::G_LSHR: {
6265 unsigned SrcIdx = PartIdx + ShiftWords;
6266 if (SrcIdx >= NumParts)
6268 if (!NeedsInterWordShift)
6269 return SrcParts[SrcIdx];
6273 if (SrcIdx + 1 < NumParts) {
6274 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6278 return Lo.getReg(0);
6281 case TargetOpcode::G_ASHR: {
6283 unsigned SrcIdx = PartIdx + ShiftWords;
6284 if (SrcIdx >= NumParts)
6286 if (!NeedsInterWordShift)
6287 return SrcParts[SrcIdx];
6292 (SrcIdx == NumParts - 1)
6296 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6318 unsigned MainOpcode =
6319 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6323 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6332 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6333 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6335 auto IsZeroBitShift =
6343 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6344 : TargetOpcode::G_SHL;
6347 auto TargetBitsConst =
6349 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6354 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6359 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6361 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6365 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6378 LLT DstTy = MRI.getType(DstReg);
6382 const unsigned NumParts = DstBits / TargetBits;
6384 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6394 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6395 MI.eraseFromParent();
6400 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6401 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6407 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6411 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6414 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6415 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6419 for (
unsigned I = 0;
I < NumParts; ++
I)
6421 Params, TargetTy, ShiftAmtTy);
6423 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6424 MI.eraseFromParent();
6433 LLT DstTy = MRI.getType(DstReg);
6434 LLT ShiftAmtTy = MRI.getType(AmtReg);
6438 const unsigned NumParts = DstBits / TargetBits;
6440 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6457 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6469 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6470 auto TargetBitsLog2Const =
6471 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6472 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6475 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6477 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6485 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6486 auto TargetBitsMinusOneConst =
6487 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6489 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6490 TargetBitsMinusOneConst)
6493 FillValue = ZeroReg;
6501 for (
unsigned I = 0;
I < NumParts; ++
I) {
6503 Register InBoundsResult = FillValue;
6513 for (
unsigned K = 0; K < NumParts; ++K) {
6514 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6516 WordShift, WordShiftKConst);
6528 switch (
MI.getOpcode()) {
6529 case TargetOpcode::G_SHL:
6530 MainSrcIdx = (int)
I - (
int)K;
6531 CarrySrcIdx = MainSrcIdx - 1;
6533 case TargetOpcode::G_LSHR:
6534 case TargetOpcode::G_ASHR:
6535 MainSrcIdx = (int)
I + (
int)K;
6536 CarrySrcIdx = MainSrcIdx + 1;
6544 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6545 Register MainOp = SrcParts[MainSrcIdx];
6549 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6550 CarryOp = SrcParts[CarrySrcIdx];
6551 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6552 CarrySrcIdx >= (
int)NumParts)
6553 CarryOp = FillValue;
6559 ResultForK = FillValue;
6565 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6572 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6576 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6577 MI.eraseFromParent();
6584 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6587 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6602 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6607 "getNeutralElementForVecReduce called with invalid opcode!");
6608 case TargetOpcode::G_VECREDUCE_ADD:
6609 case TargetOpcode::G_VECREDUCE_OR:
6610 case TargetOpcode::G_VECREDUCE_XOR:
6611 case TargetOpcode::G_VECREDUCE_UMAX:
6613 case TargetOpcode::G_VECREDUCE_MUL:
6615 case TargetOpcode::G_VECREDUCE_AND:
6616 case TargetOpcode::G_VECREDUCE_UMIN:
6619 case TargetOpcode::G_VECREDUCE_SMAX:
6622 case TargetOpcode::G_VECREDUCE_SMIN:
6625 case TargetOpcode::G_VECREDUCE_FADD:
6627 case TargetOpcode::G_VECREDUCE_FMUL:
6629 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6630 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6631 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6632 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6640 unsigned Opc =
MI.getOpcode();
6642 case TargetOpcode::G_IMPLICIT_DEF:
6643 case TargetOpcode::G_LOAD: {
6651 case TargetOpcode::G_STORE:
6658 case TargetOpcode::G_AND:
6659 case TargetOpcode::G_OR:
6660 case TargetOpcode::G_XOR:
6661 case TargetOpcode::G_ADD:
6662 case TargetOpcode::G_SUB:
6663 case TargetOpcode::G_MUL:
6664 case TargetOpcode::G_FADD:
6665 case TargetOpcode::G_FSUB:
6666 case TargetOpcode::G_FMUL:
6667 case TargetOpcode::G_FDIV:
6668 case TargetOpcode::G_FCOPYSIGN:
6669 case TargetOpcode::G_UADDSAT:
6670 case TargetOpcode::G_USUBSAT:
6671 case TargetOpcode::G_SADDSAT:
6672 case TargetOpcode::G_SSUBSAT:
6673 case TargetOpcode::G_SMIN:
6674 case TargetOpcode::G_SMAX:
6675 case TargetOpcode::G_UMIN:
6676 case TargetOpcode::G_UMAX:
6677 case TargetOpcode::G_FMINNUM:
6678 case TargetOpcode::G_FMAXNUM:
6679 case TargetOpcode::G_FMINNUM_IEEE:
6680 case TargetOpcode::G_FMAXNUM_IEEE:
6681 case TargetOpcode::G_FMINIMUM:
6682 case TargetOpcode::G_FMAXIMUM:
6683 case TargetOpcode::G_FMINIMUMNUM:
6684 case TargetOpcode::G_FMAXIMUMNUM:
6685 case TargetOpcode::G_STRICT_FADD:
6686 case TargetOpcode::G_STRICT_FSUB:
6687 case TargetOpcode::G_STRICT_FMUL: {
6695 case TargetOpcode::G_SHL:
6696 case TargetOpcode::G_ASHR:
6697 case TargetOpcode::G_LSHR: {
6703 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6709 case TargetOpcode::G_FMA:
6710 case TargetOpcode::G_STRICT_FMA:
6711 case TargetOpcode::G_FSHR:
6712 case TargetOpcode::G_FSHL: {
6721 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6722 case TargetOpcode::G_EXTRACT:
6729 case TargetOpcode::G_INSERT:
6730 case TargetOpcode::G_INSERT_VECTOR_ELT:
6731 case TargetOpcode::G_FREEZE:
6732 case TargetOpcode::G_FNEG:
6733 case TargetOpcode::G_FABS:
6734 case TargetOpcode::G_FSQRT:
6735 case TargetOpcode::G_FCEIL:
6736 case TargetOpcode::G_FFLOOR:
6737 case TargetOpcode::G_FNEARBYINT:
6738 case TargetOpcode::G_FRINT:
6739 case TargetOpcode::G_INTRINSIC_ROUND:
6740 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6741 case TargetOpcode::G_INTRINSIC_TRUNC:
6742 case TargetOpcode::G_BITREVERSE:
6743 case TargetOpcode::G_BSWAP:
6744 case TargetOpcode::G_FCANONICALIZE:
6745 case TargetOpcode::G_SEXT_INREG:
6746 case TargetOpcode::G_ABS:
6747 case TargetOpcode::G_CTLZ:
6748 case TargetOpcode::G_CTPOP:
6756 case TargetOpcode::G_SELECT: {
6757 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6759 if (!CondTy.isScalar() ||
6765 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6767 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6772 if (CondTy.isVector())
6782 case TargetOpcode::G_UNMERGE_VALUES:
6784 case TargetOpcode::G_PHI:
6786 case TargetOpcode::G_SHUFFLE_VECTOR:
6788 case TargetOpcode::G_BUILD_VECTOR: {
6790 for (
auto Op :
MI.uses()) {
6798 MIRBuilder.buildDeleteTrailingVectorElements(
6799 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6800 MI.eraseFromParent();
6803 case TargetOpcode::G_SEXT:
6804 case TargetOpcode::G_ZEXT:
6805 case TargetOpcode::G_ANYEXT:
6806 case TargetOpcode::G_TRUNC:
6807 case TargetOpcode::G_FPTRUNC:
6808 case TargetOpcode::G_FPEXT:
6809 case TargetOpcode::G_FPTOSI:
6810 case TargetOpcode::G_FPTOUI:
6811 case TargetOpcode::G_FPTOSI_SAT:
6812 case TargetOpcode::G_FPTOUI_SAT:
6813 case TargetOpcode::G_SITOFP:
6814 case TargetOpcode::G_UITOFP: {
6821 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6824 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6832 case TargetOpcode::G_ICMP:
6833 case TargetOpcode::G_FCMP: {
6842 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6847 case TargetOpcode::G_BITCAST: {
6851 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6852 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6868 case TargetOpcode::G_VECREDUCE_FADD:
6869 case TargetOpcode::G_VECREDUCE_FMUL:
6870 case TargetOpcode::G_VECREDUCE_ADD:
6871 case TargetOpcode::G_VECREDUCE_MUL:
6872 case TargetOpcode::G_VECREDUCE_AND:
6873 case TargetOpcode::G_VECREDUCE_OR:
6874 case TargetOpcode::G_VECREDUCE_XOR:
6875 case TargetOpcode::G_VECREDUCE_SMAX:
6876 case TargetOpcode::G_VECREDUCE_SMIN:
6877 case TargetOpcode::G_VECREDUCE_UMAX:
6878 case TargetOpcode::G_VECREDUCE_UMIN: {
6879 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6881 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6882 auto NeutralElement = getNeutralElementForVecReduce(
6888 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6889 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6890 NeutralElement, Idx);
6894 MO.
setReg(NewVec.getReg(0));
6906 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6908 unsigned MaskNumElts = Mask.size();
6909 unsigned SrcNumElts = SrcTy.getNumElements();
6912 if (MaskNumElts == SrcNumElts)
6915 if (MaskNumElts < SrcNumElts) {
6923 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6924 MI.getOperand(1).getReg(),
6925 MI.getOperand(2).getReg(), NewMask);
6926 MI.eraseFromParent();
6931 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6932 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6940 MOps1[0] =
MI.getOperand(1).getReg();
6941 MOps2[0] =
MI.getOperand(2).getReg();
6943 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6944 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6948 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6950 if (Idx >=
static_cast<int>(SrcNumElts))
6951 Idx += PaddedMaskNumElts - SrcNumElts;
6956 if (MaskNumElts != PaddedMaskNumElts) {
6958 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6961 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6963 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6968 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6971 MI.eraseFromParent();
6977 unsigned int TypeIdx,
LLT MoreTy) {
6978 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6980 unsigned NumElts = DstTy.getNumElements();
6983 if (DstTy.isVector() && Src1Ty.isVector() &&
6984 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6992 if (DstTy != Src1Ty || DstTy != Src2Ty)
7000 for (
unsigned I = 0;
I != NumElts; ++
I) {
7002 if (Idx <
static_cast<int>(NumElts))
7005 NewMask[
I] = Idx - NumElts + WidenNumElts;
7009 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7010 MI.getOperand(1).getReg(),
7011 MI.getOperand(2).getReg(), NewMask);
7012 MI.eraseFromParent();
7021 unsigned SrcParts = Src1Regs.
size();
7022 unsigned DstParts = DstRegs.
size();
7024 unsigned DstIdx = 0;
7026 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7027 DstRegs[DstIdx] = FactorSum;
7032 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7034 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7035 i <= std::min(DstIdx, SrcParts - 1); ++i) {
7037 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7041 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7042 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7044 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7054 if (DstIdx != DstParts - 1) {
7055 MachineInstrBuilder Uaddo =
7056 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
7057 FactorSum = Uaddo.
getReg(0);
7058 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7059 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7060 MachineInstrBuilder Uaddo =
7061 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
7062 FactorSum = Uaddo.
getReg(0);
7063 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7064 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7068 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7069 for (
unsigned i = 2; i < Factors.
size(); ++i)
7070 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7073 CarrySumPrevDstIdx = CarrySum;
7074 DstRegs[DstIdx] = FactorSum;
7086 LLT DstType = MRI.getType(DstReg);
7088 if (DstType.isVector())
7091 unsigned Opcode =
MI.getOpcode();
7092 unsigned OpO, OpE, OpF;
7094 case TargetOpcode::G_SADDO:
7095 case TargetOpcode::G_SADDE:
7096 case TargetOpcode::G_UADDO:
7097 case TargetOpcode::G_UADDE:
7098 case TargetOpcode::G_ADD:
7099 OpO = TargetOpcode::G_UADDO;
7100 OpE = TargetOpcode::G_UADDE;
7101 OpF = TargetOpcode::G_UADDE;
7102 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7103 OpF = TargetOpcode::G_SADDE;
7105 case TargetOpcode::G_SSUBO:
7106 case TargetOpcode::G_SSUBE:
7107 case TargetOpcode::G_USUBO:
7108 case TargetOpcode::G_USUBE:
7109 case TargetOpcode::G_SUB:
7110 OpO = TargetOpcode::G_USUBO;
7111 OpE = TargetOpcode::G_USUBE;
7112 OpF = TargetOpcode::G_USUBE;
7113 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7114 OpF = TargetOpcode::G_SSUBE;
7121 unsigned NumDefs =
MI.getNumExplicitDefs();
7122 Register Src1 =
MI.getOperand(NumDefs).getReg();
7123 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7126 CarryDst =
MI.getOperand(1).getReg();
7127 if (
MI.getNumOperands() == NumDefs + 3)
7128 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7130 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7131 LLT LeftoverTy, DummyTy;
7133 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7138 int NarrowParts = Src1Regs.
size();
7139 Src1Regs.
append(Src1Left);
7140 Src2Regs.
append(Src2Left);
7143 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7145 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7148 if (i == e - 1 && CarryDst)
7149 CarryOut = CarryDst;
7151 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7154 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7155 {Src1Regs[i], Src2Regs[i]});
7156 }
else if (i == e - 1) {
7157 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7158 {Src1Regs[i], Src2Regs[i], CarryIn});
7160 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7161 {Src1Regs[i], Src2Regs[i], CarryIn});
7167 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7168 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7169 ArrayRef(DstRegs).drop_front(NarrowParts));
7171 MI.eraseFromParent();
7177 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7179 LLT Ty = MRI.getType(DstReg);
7183 unsigned Size = Ty.getSizeInBits();
7185 if (
Size % NarrowSize != 0)
7188 unsigned NumParts =
Size / NarrowSize;
7189 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7190 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7196 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7200 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7201 MI.eraseFromParent();
7211 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7214 LLT SrcTy = MRI.getType(Src);
7225 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7238 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7241 if (SizeOp1 % NarrowSize != 0)
7243 int NumParts = SizeOp1 / NarrowSize;
7246 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7250 uint64_t OpStart =
MI.getOperand(2).getImm();
7251 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7252 for (
int i = 0; i < NumParts; ++i) {
7253 unsigned SrcStart = i * NarrowSize;
7255 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7258 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7266 int64_t ExtractOffset;
7268 if (OpStart < SrcStart) {
7270 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7272 ExtractOffset = OpStart - SrcStart;
7273 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7277 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7279 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7280 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7287 if (MRI.getType(DstReg).isVector())
7288 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7289 else if (DstRegs.
size() > 1)
7290 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7293 MI.eraseFromParent();
7305 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7307 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7310 SrcRegs.
append(LeftoverRegs);
7314 uint64_t OpStart =
MI.getOperand(3).getImm();
7315 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7316 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7317 unsigned DstStart =
I * NarrowSize;
7319 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7327 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7329 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7333 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7341 int64_t ExtractOffset, InsertOffset;
7343 if (OpStart < DstStart) {
7345 ExtractOffset = DstStart - OpStart;
7346 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7348 InsertOffset = OpStart - DstStart;
7351 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7355 if (ExtractOffset != 0 || SegSize != OpSize) {
7357 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7358 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7361 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7362 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7370 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7373 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7375 MI.eraseFromParent();
7383 LLT DstTy = MRI.getType(DstReg);
7385 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7391 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7392 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7396 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7397 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7400 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7401 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7402 {Src0Regs[I], Src1Regs[I]});
7406 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7409 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7410 DstLeftoverRegs.
push_back(Inst.getReg(0));
7413 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7414 LeftoverTy, DstLeftoverRegs);
7416 MI.eraseFromParent();
7426 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7428 LLT DstTy = MRI.getType(DstReg);
7433 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7434 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7435 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7437 MI.eraseFromParent();
7447 Register CondReg =
MI.getOperand(1).getReg();
7448 LLT CondTy = MRI.getType(CondReg);
7453 LLT DstTy = MRI.getType(DstReg);
7459 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7460 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7464 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7465 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7468 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7470 CondReg, Src1Regs[
I], Src2Regs[
I]);
7474 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7476 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7480 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7481 LeftoverTy, DstLeftoverRegs);
7483 MI.eraseFromParent();
7493 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7496 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7497 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7500 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7502 auto C_0 =
B.buildConstant(NarrowTy, 0);
7504 UnmergeSrc.getReg(1), C_0);
7505 auto LoCTLZ = IsUndef ?
7506 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7507 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7508 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7509 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7510 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7511 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7513 MI.eraseFromParent();
7526 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7529 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7530 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7533 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7535 auto C_0 =
B.buildConstant(NarrowTy, 0);
7537 UnmergeSrc.getReg(0), C_0);
7538 auto HiCTTZ = IsUndef ?
7539 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7540 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7541 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7542 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7543 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7544 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7546 MI.eraseFromParent();
7559 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7562 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7563 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7565 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7566 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7567 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7569 MI.eraseFromParent();
7584 LLT ExpTy = MRI.getType(ExpReg);
7589 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7590 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7591 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7592 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7594 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7596 MI.getOperand(2).setReg(Trunc.getReg(0));
7603 unsigned Opc =
MI.getOpcode();
7606 auto QAction = LI.getAction(Q).Action;
7612 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7615 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7619 case TargetOpcode::G_CTLZ: {
7620 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7621 unsigned Len = SrcTy.getScalarSizeInBits();
7623 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7625 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7626 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7629 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7630 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7631 MI.eraseFromParent();
7647 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7648 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7651 Op = MIBOp.getReg(0);
7656 MI.eraseFromParent();
7659 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7662 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7666 case TargetOpcode::G_CTTZ: {
7667 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7669 unsigned Len = SrcTy.getScalarSizeInBits();
7670 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7673 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7674 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7677 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7678 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7679 MI.eraseFromParent();
7686 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7687 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7689 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7690 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7691 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7692 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7695 MI.eraseFromParent();
7699 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7700 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7704 case TargetOpcode::G_CTPOP: {
7706 LLT Ty = MRI.getType(SrcReg);
7707 unsigned Size = Ty.getScalarSizeInBits();
7719 auto C_1 =
B.buildConstant(Ty, 1);
7720 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7722 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7723 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7724 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7728 auto C_2 =
B.buildConstant(Ty, 2);
7729 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7731 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7732 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7733 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7734 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7741 auto C_4 =
B.buildConstant(Ty, 4);
7742 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7743 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7745 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7746 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7748 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7754 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7756 auto IsMulSupported = [
this](
const LLT Ty) {
7757 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7760 if (IsMulSupported(Ty)) {
7761 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7762 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7764 auto ResTmp = B8Count;
7765 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7766 auto ShiftC =
B.buildConstant(Ty, Shift);
7767 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7768 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7770 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7772 MI.eraseFromParent();
7793 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7794 LLT Ty = MRI.getType(Dst);
7795 LLT ShTy = MRI.getType(Z);
7802 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7803 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7808 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7809 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7813 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7826 MI.eraseFromParent();
7832 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7833 LLT Ty = MRI.getType(Dst);
7834 LLT ShTy = MRI.getType(Z);
7837 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7847 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7848 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7849 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7850 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7851 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7855 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7858 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7861 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7863 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7864 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7865 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7868 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7870 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7872 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7875 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7876 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7881 MI.eraseFromParent();
7892 LLT Ty = MRI.getType(Dst);
7893 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7895 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7896 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7899 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7900 return lowerFunnelShiftAsShifts(
MI);
7904 if (Result == UnableToLegalize)
7905 return lowerFunnelShiftAsShifts(
MI);
7910 auto [Dst, Src] =
MI.getFirst2Regs();
7911 LLT DstTy = MRI.getType(Dst);
7912 LLT SrcTy = MRI.getType(Src);
7916 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7924 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7928 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7932 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7937 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7938 {UnmergeSrc.getReg(0)});
7939 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7940 {UnmergeSrc.getReg(1)});
7943 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7945 MI.eraseFromParent();
7962 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7966 LLT DstTy = MRI.getType(DstReg);
7967 LLT SrcTy = MRI.getType(SrcReg);
7975 SrcTy.getElementCount().divideCoefficientBy(2));
7988 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8000 MI.eraseFromParent();
8009 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8010 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8011 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8012 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8013 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8014 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8015 MI.eraseFromParent();
8020 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8022 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8023 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8028 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8029 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8031 return lowerRotateWithReverseRotate(
MI);
8034 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8035 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8036 bool IsFShLegal =
false;
8037 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8038 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8042 MI.eraseFromParent();
8047 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8050 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8055 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8056 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8057 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8063 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8064 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8066 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8072 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8073 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8075 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8077 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8081 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
8082 MI.eraseFromParent();
8090 auto [Dst, Src] =
MI.getFirst2Regs();
8095 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8123 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8136 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8140 MI.eraseFromParent();
8148 auto [Dst, Src] =
MI.getFirst2Regs();
8153 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8166 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8168 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8173 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8175 MI.eraseFromParent();
8183 auto [Dst, Src] =
MI.getFirst2Regs();
8187 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8198 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8199 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8201 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8208 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8209 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8210 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8212 MI.eraseFromParent();
8222 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8228 MI.eraseFromParent();
8233 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8236 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8237 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8238 MIRBuilder.buildSelect(Dst, Src, True, False);
8239 MI.eraseFromParent();
8243 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8263 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8270 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8271 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8272 MIRBuilder.buildSelect(Dst, Src, True, False);
8273 MI.eraseFromParent();
8277 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8300 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8301 MI.eraseFromParent();
8309 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8313 if (SrcTy !=
S64 && SrcTy !=
S32)
8315 if (DstTy !=
S32 && DstTy !=
S64)
8342 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8344 MI.eraseFromParent();
8349 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8354 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8361 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8363 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8364 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8366 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8367 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8369 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8371 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8372 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8373 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8376 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8377 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8378 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8380 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8383 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8388 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8389 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8395 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8397 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8398 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8400 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8405 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8406 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8408 MI.eraseFromParent();
8414 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8416 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8417 unsigned SatWidth = DstTy.getScalarSizeInBits();
8421 APInt MinInt, MaxInt;
8444 if (AreExactFloatBounds) {
8446 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8448 SrcTy.changeElementSize(1), Src, MaxC);
8449 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8451 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8461 MI.eraseFromParent();
8466 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8468 DstTy.changeElementSize(1), Src, Src);
8471 MI.eraseFromParent();
8478 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8487 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8498 MI.eraseFromParent();
8504 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8506 DstTy.changeElementSize(1), Src, Src);
8508 MI.eraseFromParent();
8518 auto [Dst, Src] =
MI.getFirst2Regs();
8520 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8522 if (MRI.getType(Src).isVector())
8526 unsigned Flags =
MI.getFlags();
8529 MI.eraseFromParent();
8533 const unsigned ExpMask = 0x7ff;
8534 const unsigned ExpBiasf64 = 1023;
8535 const unsigned ExpBiasf16 = 15;
8564 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8624 MI.eraseFromParent();
8630 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8634 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8641 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8642 LLT Ty = MRI.getType(Dst);
8644 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8645 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8646 MI.eraseFromParent();
8652 case TargetOpcode::G_SMIN:
8654 case TargetOpcode::G_SMAX:
8656 case TargetOpcode::G_UMIN:
8658 case TargetOpcode::G_UMAX:
8666 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8671 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8672 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8674 MI.eraseFromParent();
8683 LLT DstTy = MRI.getType(Dst);
8684 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8694 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8695 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8697 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8700 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8701 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8702 if (TLI.preferSelectsOverBooleanArithmetic(
8705 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8706 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8708 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8709 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8715 unsigned BoolExtOp =
8717 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8718 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8722 MI.eraseFromParent();
8728 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8729 const int Src0Size = Src0Ty.getScalarSizeInBits();
8730 const int Src1Size = Src1Ty.getScalarSizeInBits();
8735 auto NotSignBitMask =
MIRBuilder.buildConstant(
8740 if (Src0Ty == Src1Ty) {
8741 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8742 }
else if (Src0Size > Src1Size) {
8743 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8744 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8745 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8746 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8748 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8749 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8750 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8751 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8757 unsigned Flags =
MI.getFlags();
8764 MI.eraseFromParent();
8775 switch (
MI.getOpcode()) {
8776 case TargetOpcode::G_FMINNUM:
8777 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8779 case TargetOpcode::G_FMINIMUMNUM:
8780 NewOp = TargetOpcode::G_FMINNUM;
8782 case TargetOpcode::G_FMAXNUM:
8783 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8785 case TargetOpcode::G_FMAXIMUMNUM:
8786 NewOp = TargetOpcode::G_FMAXNUM;
8792 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8793 LLT Ty = MRI.getType(Dst);
8803 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8806 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8811 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8812 MI.eraseFromParent();
8818 unsigned Opc =
MI.getOpcode();
8819 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8820 LLT Ty = MRI.getType(Dst);
8823 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
8825 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
8826 unsigned OpcNonIeee =
8827 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
8828 bool MinMaxMustRespectOrderedZero =
false;
8832 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
8834 MinMaxMustRespectOrderedZero =
true;
8835 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
8840 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
8848 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
8852 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
8854 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
8864 const unsigned Flags =
MI.getFlags();
8870 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
8872 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
8874 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
8876 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
8878 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
8883 MI.eraseFromParent();
8890 LLT Ty = MRI.getType(DstReg);
8891 unsigned Flags =
MI.getFlags();
8896 MI.eraseFromParent();
8902 auto [DstReg,
X] =
MI.getFirst2Regs();
8903 const unsigned Flags =
MI.getFlags();
8904 const LLT Ty = MRI.getType(DstReg);
8916 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8918 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8923 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8924 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8925 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8926 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8928 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8930 MI.eraseFromParent();
8935 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8936 unsigned Flags =
MI.getFlags();
8937 LLT Ty = MRI.getType(DstReg);
8944 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8945 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8948 SrcReg, Zero, Flags);
8950 SrcReg, Trunc, Flags);
8954 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8955 MI.eraseFromParent();
8961 const unsigned NumOps =
MI.getNumOperands();
8962 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8963 unsigned PartSize = Src0Ty.getSizeInBits();
8968 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8969 const unsigned Offset = (
I - 1) * PartSize;
8972 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8975 MRI.createGenericVirtualRegister(WideTy);
8978 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8979 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8980 ResultReg = NextResult;
8983 if (DstTy.isPointer()) {
8984 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8985 DstTy.getAddressSpace())) {
8993 MI.eraseFromParent();
8999 const unsigned NumDst =
MI.getNumOperands() - 1;
9000 Register SrcReg =
MI.getOperand(NumDst).getReg();
9001 Register Dst0Reg =
MI.getOperand(0).getReg();
9002 LLT DstTy = MRI.getType(Dst0Reg);
9011 LLT IntTy = MRI.getType(SrcReg);
9016 unsigned Offset = DstSize;
9017 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9019 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9023 MI.eraseFromParent();
9042 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9043 InsertVal =
MI.getOperand(2).getReg();
9045 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9047 LLT VecTy = MRI.getType(SrcVec);
9057 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9058 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9060 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9063 MI.eraseFromParent();
9068 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9079 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9086 int64_t
Offset = IdxVal * EltBytes;
9097 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9100 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9102 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9105 MI.eraseFromParent();
9111 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9112 MI.getFirst3RegLLTs();
9122 for (
int Idx : Mask) {
9124 if (!Undef.isValid())
9125 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
9130 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9132 int NumElts = Src0Ty.getNumElements();
9133 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9134 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9135 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9137 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9139 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9144 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9145 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9146 MI.eraseFromParent();
9152 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9153 MI.getFirst4RegLLTs();
9155 if (VecTy.isScalableVector())
9171 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9174 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9177 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9180 std::optional<APInt> PassthruSplatVal =
9183 if (PassthruSplatVal.has_value()) {
9185 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9186 }
else if (HasPassthru) {
9187 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9188 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9194 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9198 unsigned NumElmts = VecTy.getNumElements();
9199 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9201 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9204 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9207 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9212 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9214 if (HasPassthru &&
I == NumElmts - 1) {
9217 auto AllLanesSelected =
MIRBuilder.buildICmp(
9219 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9220 {OutPos, EndOfVector});
9224 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9226 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9231 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9233 MI.eraseFromParent();
9244 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9250 if (Alignment >
Align(1)) {
9253 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9262 const auto &MF = *
MI.getMF();
9268 Register AllocSize =
MI.getOperand(1).getReg();
9271 LLT PtrTy = MRI.getType(Dst);
9272 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9279 MI.eraseFromParent();
9285 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9290 MI.eraseFromParent();
9296 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9301 MI.eraseFromParent();
9307 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9308 unsigned Offset =
MI.getOperand(2).getImm();
9311 if (SrcTy.isVector()) {
9312 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9313 unsigned DstSize = DstTy.getSizeInBits();
9315 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9316 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9318 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9322 for (
unsigned Idx =
Offset / SrcEltSize;
9323 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9324 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9326 if (SubVectorElts.
size() == 1)
9327 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9329 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9331 MI.eraseFromParent();
9336 if (DstTy.isScalar() &&
9337 (SrcTy.isScalar() ||
9338 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9339 LLT SrcIntTy = SrcTy;
9340 if (!SrcTy.isScalar()) {
9342 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9349 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9353 MI.eraseFromParent();
9361 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9364 LLT DstTy = MRI.getType(Src);
9365 LLT InsertTy = MRI.getType(InsertSrc);
9373 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9375 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9379 for (; Idx <
Offset / EltSize; ++Idx) {
9380 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9385 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9386 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9388 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9397 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9400 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9401 MI.eraseFromParent();
9415 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9419 LLT IntDstTy = DstTy;
9423 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9428 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9434 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9440 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9441 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9442 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9445 MI.eraseFromParent();
9451 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9452 MI.getFirst4RegLLTs();
9453 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9456 LLT BoolTy = Dst1Ty;
9458 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9475 auto ResultLowerThanLHS =
9480 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9483 MI.eraseFromParent();
9489 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9490 const LLT Ty = MRI.getType(Res);
9493 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9494 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9495 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9506 MI.eraseFromParent();
9511 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9512 const LLT Ty = MRI.getType(Res);
9515 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9516 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9517 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9522 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9527 MI.eraseFromParent();
9533 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9534 LLT Ty = MRI.getType(Res);
9538 switch (
MI.getOpcode()) {
9541 case TargetOpcode::G_UADDSAT:
9544 BaseOp = TargetOpcode::G_ADD;
9546 case TargetOpcode::G_SADDSAT:
9549 BaseOp = TargetOpcode::G_ADD;
9551 case TargetOpcode::G_USUBSAT:
9554 BaseOp = TargetOpcode::G_SUB;
9556 case TargetOpcode::G_SSUBSAT:
9559 BaseOp = TargetOpcode::G_SUB;
9574 uint64_t NumBits = Ty.getScalarSizeInBits();
9585 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9593 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9598 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9599 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9602 MI.eraseFromParent();
9608 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9609 LLT Ty = MRI.getType(Res);
9613 unsigned OverflowOp;
9614 switch (
MI.getOpcode()) {
9617 case TargetOpcode::G_UADDSAT:
9620 OverflowOp = TargetOpcode::G_UADDO;
9622 case TargetOpcode::G_SADDSAT:
9625 OverflowOp = TargetOpcode::G_SADDO;
9627 case TargetOpcode::G_USUBSAT:
9630 OverflowOp = TargetOpcode::G_USUBO;
9632 case TargetOpcode::G_SSUBSAT:
9635 OverflowOp = TargetOpcode::G_SSUBO;
9640 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9641 Register Tmp = OverflowRes.getReg(0);
9642 Register Ov = OverflowRes.getReg(1);
9651 uint64_t NumBits = Ty.getScalarSizeInBits();
9652 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9653 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9656 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9664 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9668 MI.eraseFromParent();
9674 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9675 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9676 "Expected shlsat opcode!");
9677 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9678 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9679 LLT Ty = MRI.getType(Res);
9683 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9684 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9693 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9698 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9700 MI.eraseFromParent();
9705 auto [Dst, Src] =
MI.getFirst2Regs();
9706 const LLT Ty = MRI.getType(Src);
9707 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9708 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9711 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9712 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9713 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9714 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9717 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9719 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9720 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9721 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9723 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9724 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9725 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9727 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9728 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9729 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9731 Res.getInstr()->getOperand(0).setReg(Dst);
9733 MI.eraseFromParent();
9740 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9743 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9744 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9745 return B.buildOr(Dst,
LHS,
RHS);
9750 auto [Dst, Src] =
MI.getFirst2Regs();
9751 const LLT SrcTy = MRI.getType(Src);
9752 unsigned Size = SrcTy.getScalarSizeInBits();
9753 unsigned VSize = SrcTy.getSizeInBits();
9756 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9757 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9758 {LLT::fixed_vector(VSize / 8, 8),
9759 LLT::fixed_vector(VSize / 8, 8)}}))) {
9764 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9765 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9766 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9770 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9793 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9797 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9800 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9804 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9808 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9813 MI.eraseFromParent();
9821 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9822 int NameOpIdx = IsRead ? 1 : 0;
9823 int ValRegIndex = IsRead ? 0 : 1;
9825 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9826 const LLT Ty = MRI.getType(ValReg);
9828 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9835 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9836 Fn,
MI.getDebugLoc()));
9840 MI.eraseFromParent();
9849 MI.eraseFromParent();
9855 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9856 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9858 LLT OrigTy = MRI.getType(Result);
9862 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9863 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9865 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9867 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9868 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9871 MI.eraseFromParent();
9877 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9882 MI.eraseFromParent();
9887 MI.eraseFromParent();
9894 unsigned BitSize = SrcTy.getScalarSizeInBits();
9898 if (SrcTy.isVector())
9899 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9900 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9906 APInt ExpMask = Inf;
9912 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9913 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9914 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9915 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9916 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9918 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9922 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9924 LLT DstTyCopy = DstTy;
9926 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9954 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9957 Mask &= ~PartialCheck;
9966 else if (PartialCheck ==
fcZero)
9978 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9979 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9982 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9984 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9985 appendToRes(SubnormalRes);
9992 else if (PartialCheck ==
fcInf)
9997 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10004 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10005 if (PartialCheck ==
fcNan) {
10009 }
else if (PartialCheck ==
fcQNan) {
10019 Abs, InfWithQnanBitC);
10020 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10027 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10029 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10030 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10033 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10035 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10038 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10039 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10041 appendToRes(NormalRes);
10045 MI.eraseFromParent();
10051 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10052 MI.getFirst4RegLLTs();
10054 bool IsEltPtr = DstTy.isPointerOrPointerVector();
10058 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10059 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10063 if (MaskTy.isScalar()) {
10071 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10075 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
10077 if (DstTy.isVector()) {
10079 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
10080 MaskReg = ShufSplat.getReg(0);
10085 }
else if (!DstTy.isVector()) {
10090 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10094 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10095 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10096 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10103 MI.eraseFromParent();
10109 unsigned Opcode =
MI.getOpcode();
10112 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10113 : TargetOpcode::G_UDIV,
10114 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10116 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10117 : TargetOpcode::G_UREM,
10118 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10119 MI.eraseFromParent();
10129 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10133 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10136 MI.eraseFromParent();
10146 Register SrcReg =
MI.getOperand(1).getReg();
10147 LLT Ty = MRI.getType(SrcReg);
10148 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10151 MI.eraseFromParent();
10157 Register SrcReg =
MI.getOperand(1).getReg();
10158 Register DestReg =
MI.getOperand(0).getReg();
10160 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10161 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10164 MI.eraseFromParent();
10170 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10171 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10172 "Expected G_ABDS or G_ABDU instruction");
10174 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10175 LLT Ty = MRI.getType(LHS);
10185 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10187 MI.eraseFromParent();
10193 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10194 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10195 "Expected G_ABDS or G_ABDU instruction");
10197 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10198 LLT Ty = MRI.getType(LHS);
10203 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10204 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10205 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10207 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10208 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10210 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10212 MI.eraseFromParent();
10217 Register SrcReg =
MI.getOperand(1).getReg();
10218 Register DstReg =
MI.getOperand(0).getReg();
10220 LLT Ty = MRI.getType(DstReg);
10228 MI.eraseFromParent();
10234 Register SrcReg =
MI.getOperand(1).getReg();
10235 LLT SrcTy = MRI.getType(SrcReg);
10236 LLT DstTy = MRI.getType(SrcReg);
10239 if (SrcTy.isScalar()) {
10244 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10255 Register ListPtr =
MI.getOperand(1).getReg();
10256 LLT PtrTy = MRI.getType(ListPtr);
10263 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10265 const Align A(
MI.getOperand(2).getImm());
10267 if (
A > TLI.getMinStackArgumentAlignment()) {
10269 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10270 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10271 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10272 VAList = AndDst.getReg(0);
10279 LLT LLTTy = MRI.getType(Dst);
10282 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10283 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10288 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10290 Align EltAlignment =
DL.getABITypeAlign(Ty);
10293 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10295 MI.eraseFromParent();
10310 unsigned Limit,
const MemOp &
Op,
10311 unsigned DstAS,
unsigned SrcAS,
10312 const AttributeList &FuncAttributes,
10314 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10324 if (
Op.isFixedDstAlign())
10325 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10328 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10332 unsigned NumMemOps = 0;
10335 unsigned TySize = Ty.getSizeInBytes();
10336 while (TySize >
Size) {
10345 assert(NewTySize > 0 &&
"Could not find appropriate type");
10352 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10354 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10360 TySize = NewTySize;
10364 if (++NumMemOps > Limit)
10367 MemOps.push_back(Ty);
10377 unsigned NumBits = Ty.getScalarSizeInBits();
10379 if (!Ty.isVector() && ValVRegAndVal) {
10380 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10388 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10409 uint64_t KnownLen,
Align Alignment,
10411 auto &MF = *
MI.getParent()->getParent();
10416 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10418 bool DstAlignCanChange =
false;
10422 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10424 DstAlignCanChange =
true;
10426 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10427 std::vector<LLT> MemOps;
10429 const auto &DstMMO = **
MI.memoperands_begin();
10430 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10433 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10444 if (DstAlignCanChange) {
10447 Align NewAlign =
DL.getABITypeAlign(IRTy);
10448 if (NewAlign > Alignment) {
10449 Alignment = NewAlign;
10457 MachineIRBuilder MIB(
MI);
10459 LLT LargestTy = MemOps[0];
10460 for (
unsigned i = 1; i < MemOps.size(); i++)
10462 LargestTy = MemOps[i];
10474 LLT PtrTy = MRI.getType(Dst);
10475 unsigned DstOff = 0;
10476 unsigned Size = KnownLen;
10477 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10478 LLT Ty = MemOps[
I];
10480 if (TySize >
Size) {
10483 assert(
I == MemOps.size() - 1 &&
I != 0);
10484 DstOff -= TySize -
Size;
10494 TLI.isTruncateFree(LargestVT, VT))
10495 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10508 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10511 MIB.buildStore(
Value, Ptr, *StoreMMO);
10516 MI.eraseFromParent();
10522 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10524 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10526 const auto *MMOIt =
MI.memoperands_begin();
10528 bool IsVolatile =
MemOp->isVolatile();
10534 "inline memcpy with dynamic size is not yet supported");
10535 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10536 if (KnownLen == 0) {
10537 MI.eraseFromParent();
10541 const auto &DstMMO = **
MI.memoperands_begin();
10542 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10543 Align DstAlign = DstMMO.getBaseAlign();
10544 Align SrcAlign = SrcMMO.getBaseAlign();
10546 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10553 Align SrcAlign,
bool IsVolatile) {
10554 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10555 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10556 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10563 Align SrcAlign,
bool IsVolatile) {
10564 auto &MF = *
MI.getParent()->getParent();
10569 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10571 bool DstAlignCanChange =
false;
10573 Align Alignment = std::min(DstAlign, SrcAlign);
10577 DstAlignCanChange =
true;
10583 std::vector<LLT> MemOps;
10585 const auto &DstMMO = **
MI.memoperands_begin();
10586 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10592 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10598 if (DstAlignCanChange) {
10601 Align NewAlign =
DL.getABITypeAlign(IRTy);
10606 if (!
TRI->hasStackRealignment(MF))
10608 NewAlign = std::min(NewAlign, *StackAlign);
10610 if (NewAlign > Alignment) {
10611 Alignment = NewAlign;
10619 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10621 MachineIRBuilder MIB(
MI);
10627 unsigned CurrOffset = 0;
10628 unsigned Size = KnownLen;
10629 for (
auto CopyTy : MemOps) {
10632 if (CopyTy.getSizeInBytes() >
Size)
10633 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10644 if (CurrOffset != 0) {
10645 LLT SrcTy = MRI.getType(Src);
10648 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10650 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10654 if (CurrOffset != 0) {
10655 LLT DstTy = MRI.getType(Dst);
10656 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10658 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10659 CurrOffset += CopyTy.getSizeInBytes();
10660 Size -= CopyTy.getSizeInBytes();
10663 MI.eraseFromParent();
10669 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10671 auto &MF = *
MI.getParent()->getParent();
10676 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10678 bool DstAlignCanChange =
false;
10681 Align Alignment = std::min(DstAlign, SrcAlign);
10683 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10685 DstAlignCanChange =
true;
10687 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10688 std::vector<LLT> MemOps;
10690 const auto &DstMMO = **
MI.memoperands_begin();
10691 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10692 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10693 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10700 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10706 if (DstAlignCanChange) {
10709 Align NewAlign =
DL.getABITypeAlign(IRTy);
10714 if (!
TRI->hasStackRealignment(MF))
10715 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10716 NewAlign = std::min(NewAlign, *StackAlign);
10718 if (NewAlign > Alignment) {
10719 Alignment = NewAlign;
10727 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10729 MachineIRBuilder MIB(
MI);
10733 unsigned CurrOffset = 0;
10734 SmallVector<Register, 16> LoadVals;
10735 for (
auto CopyTy : MemOps) {
10742 if (CurrOffset != 0) {
10743 LLT SrcTy = MRI.getType(Src);
10746 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10748 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10749 CurrOffset += CopyTy.getSizeInBytes();
10753 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10754 LLT CopyTy = MemOps[
I];
10760 if (CurrOffset != 0) {
10761 LLT DstTy = MRI.getType(Dst);
10764 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10766 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10769 MI.eraseFromParent();
10775 const unsigned Opc =
MI.getOpcode();
10778 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10779 Opc == TargetOpcode::G_MEMSET) &&
10780 "Expected memcpy like instruction");
10782 auto MMOIt =
MI.memoperands_begin();
10787 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10789 if (
Opc != TargetOpcode::G_MEMSET) {
10790 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10791 MemOp = *(++MMOIt);
10792 SrcAlign =
MemOp->getBaseAlign();
10797 if (!LenVRegAndVal)
10799 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10801 if (KnownLen == 0) {
10802 MI.eraseFromParent();
10806 if (MaxLen && KnownLen > MaxLen)
10809 bool IsVolatile =
MemOp->isVolatile();
10810 if (
Opc == TargetOpcode::G_MEMCPY) {
10811 auto &MF = *
MI.getParent()->getParent();
10814 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10815 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10818 if (
Opc == TargetOpcode::G_MEMMOVE)
10819 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10820 if (
Opc == TargetOpcode::G_MEMSET)
10821 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)