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.getMemcpyName();
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_FPTOSI:
3069 case TargetOpcode::G_FPTOUI:
3070 case TargetOpcode::G_INTRINSIC_LRINT:
3071 case TargetOpcode::G_INTRINSIC_LLRINT:
3072 case TargetOpcode::G_IS_FPCLASS:
3082 case TargetOpcode::G_SITOFP:
3092 case TargetOpcode::G_UITOFP:
3102 case TargetOpcode::G_FPTOSI_SAT:
3103 case TargetOpcode::G_FPTOUI_SAT:
3108 LLT Ty = MRI.getType(OldDst);
3109 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3111 MI.getOperand(0).setReg(ExtReg);
3112 uint64_t ShortBits = Ty.getScalarSizeInBits();
3115 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3126 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3127 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3135 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3143 case TargetOpcode::G_LOAD:
3144 case TargetOpcode::G_SEXTLOAD:
3145 case TargetOpcode::G_ZEXTLOAD:
3151 case TargetOpcode::G_STORE: {
3155 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3156 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3157 if (!Ty.isScalar()) {
3165 MI.setMemRefs(MF, {NewMMO});
3172 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3173 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3179 case TargetOpcode::G_CONSTANT: {
3182 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3183 MRI.getType(
MI.getOperand(0).getReg()));
3184 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3185 ExtOpc == TargetOpcode::G_ANYEXT) &&
3188 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3192 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3198 case TargetOpcode::G_FCONSTANT: {
3204 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3206 MI.eraseFromParent();
3209 case TargetOpcode::G_IMPLICIT_DEF: {
3215 case TargetOpcode::G_BRCOND:
3221 case TargetOpcode::G_FCMP:
3232 case TargetOpcode::G_ICMP:
3237 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3241 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3242 unsigned ExtOpcode =
3246 ? TargetOpcode::G_SEXT
3247 : TargetOpcode::G_ZEXT;
3254 case TargetOpcode::G_PTR_ADD:
3255 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3261 case TargetOpcode::G_PHI: {
3262 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3265 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3277 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3280 LLT VecTy = MRI.getType(VecReg);
3285 TargetOpcode::G_ANYEXT);
3299 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3315 LLT VecTy = MRI.getType(VecReg);
3334 case TargetOpcode::G_FADD:
3335 case TargetOpcode::G_FMUL:
3336 case TargetOpcode::G_FSUB:
3337 case TargetOpcode::G_FMA:
3338 case TargetOpcode::G_FMAD:
3339 case TargetOpcode::G_FNEG:
3340 case TargetOpcode::G_FABS:
3341 case TargetOpcode::G_FCANONICALIZE:
3342 case TargetOpcode::G_FMINNUM:
3343 case TargetOpcode::G_FMAXNUM:
3344 case TargetOpcode::G_FMINNUM_IEEE:
3345 case TargetOpcode::G_FMAXNUM_IEEE:
3346 case TargetOpcode::G_FMINIMUM:
3347 case TargetOpcode::G_FMAXIMUM:
3348 case TargetOpcode::G_FMINIMUMNUM:
3349 case TargetOpcode::G_FMAXIMUMNUM:
3350 case TargetOpcode::G_FDIV:
3351 case TargetOpcode::G_FREM:
3352 case TargetOpcode::G_FCEIL:
3353 case TargetOpcode::G_FFLOOR:
3354 case TargetOpcode::G_FCOS:
3355 case TargetOpcode::G_FSIN:
3356 case TargetOpcode::G_FTAN:
3357 case TargetOpcode::G_FACOS:
3358 case TargetOpcode::G_FASIN:
3359 case TargetOpcode::G_FATAN:
3360 case TargetOpcode::G_FATAN2:
3361 case TargetOpcode::G_FCOSH:
3362 case TargetOpcode::G_FSINH:
3363 case TargetOpcode::G_FTANH:
3364 case TargetOpcode::G_FLOG10:
3365 case TargetOpcode::G_FLOG:
3366 case TargetOpcode::G_FLOG2:
3367 case TargetOpcode::G_FRINT:
3368 case TargetOpcode::G_FNEARBYINT:
3369 case TargetOpcode::G_FSQRT:
3370 case TargetOpcode::G_FEXP:
3371 case TargetOpcode::G_FEXP2:
3372 case TargetOpcode::G_FEXP10:
3373 case TargetOpcode::G_FPOW:
3374 case TargetOpcode::G_INTRINSIC_TRUNC:
3375 case TargetOpcode::G_INTRINSIC_ROUND:
3376 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3380 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3386 case TargetOpcode::G_FMODF: {
3396 case TargetOpcode::G_FPOWI:
3397 case TargetOpcode::G_FLDEXP:
3398 case TargetOpcode::G_STRICT_FLDEXP: {
3400 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3421 case TargetOpcode::G_FFREXP: {
3434 case TargetOpcode::G_INTTOPTR:
3442 case TargetOpcode::G_PTRTOINT:
3450 case TargetOpcode::G_BUILD_VECTOR: {
3454 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3460 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3468 case TargetOpcode::G_SEXT_INREG:
3477 case TargetOpcode::G_PTRMASK: {
3485 case TargetOpcode::G_VECREDUCE_ADD: {
3494 case TargetOpcode::G_VECREDUCE_FADD:
3495 case TargetOpcode::G_VECREDUCE_FMUL:
3496 case TargetOpcode::G_VECREDUCE_FMIN:
3497 case TargetOpcode::G_VECREDUCE_FMAX:
3498 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3499 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3504 LLT VecTy = MRI.getType(VecReg);
3513 case TargetOpcode::G_VSCALE: {
3520 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3525 case TargetOpcode::G_SPLAT_VECTOR: {
3534 case TargetOpcode::G_INSERT_SUBVECTOR: {
3542 LLT SubVecTy = MRI.getType(SubVec);
3546 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3547 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3548 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3552 auto SplatZero =
MIRBuilder.buildSplatVector(
3557 MI.eraseFromParent();
3566 auto Unmerge =
B.buildUnmerge(Ty, Src);
3567 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3576 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3578 LLT DstLLT =
MRI.getType(DstReg);
3590 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3599 MI.eraseFromParent();
3610 MI.eraseFromParent();
3617 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3618 if (SrcTy.isVector()) {
3622 if (DstTy.isVector()) {
3623 int NumDstElt = DstTy.getNumElements();
3624 int NumSrcElt = SrcTy.getNumElements();
3627 LLT DstCastTy = DstEltTy;
3628 LLT SrcPartTy = SrcEltTy;
3632 if (NumSrcElt < NumDstElt) {
3642 SrcPartTy = SrcEltTy;
3643 }
else if (NumSrcElt > NumDstElt) {
3654 DstCastTy = DstEltTy;
3659 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3663 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3664 MI.eraseFromParent();
3668 if (DstTy.isVector()) {
3671 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3672 MI.eraseFromParent();
3688 unsigned NewEltSize,
3689 unsigned OldEltSize) {
3690 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3691 LLT IdxTy =
B.getMRI()->getType(Idx);
3694 auto OffsetMask =
B.buildConstant(
3696 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3697 return B.buildShl(IdxTy, OffsetIdx,
3698 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3713 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3717 unsigned OldNumElts = SrcVecTy.getNumElements();
3724 if (NewNumElts > OldNumElts) {
3735 if (NewNumElts % OldNumElts != 0)
3739 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3743 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3746 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3748 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3749 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3750 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3751 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3752 NewOps[
I] = Elt.getReg(0);
3755 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3757 MI.eraseFromParent();
3761 if (NewNumElts < OldNumElts) {
3762 if (NewEltSize % OldEltSize != 0)
3784 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3785 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3788 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3792 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3793 ScaledIdx).getReg(0);
3801 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3803 MI.eraseFromParent();
3817 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3818 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3819 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3820 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3823 auto EltMask =
B.buildConstant(
3827 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3828 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3831 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3835 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3849 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3850 MI.getFirst4RegLLTs();
3862 if (NewNumElts < OldNumElts) {
3863 if (NewEltSize % OldEltSize != 0)
3872 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3873 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3876 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3880 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3881 ScaledIdx).getReg(0);
3891 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3892 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3896 MI.eraseFromParent();
3926 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3930 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3931 return UnableToLegalize;
3936 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3938 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3947 MI.eraseFromParent();
3965 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3966 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3976 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3977 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3979 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
3980 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
3982 MI.eraseFromParent();
4012 LLT DstTy = MRI.getType(Dst);
4013 LLT SrcTy = MRI.getType(Src);
4019 if (DstTy == CastTy)
4027 if (CastEltSize < DstEltSize)
4030 auto AdjustAmt = CastEltSize / DstEltSize;
4031 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4032 SrcTyMinElts % AdjustAmt != 0)
4037 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4038 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4041 ES->eraseFromParent();
4076 LLT DstTy = MRI.getType(Dst);
4077 LLT BigVecTy = MRI.getType(BigVec);
4078 LLT SubVecTy = MRI.getType(SubVec);
4080 if (DstTy == CastTy)
4095 if (CastEltSize < DstEltSize)
4098 auto AdjustAmt = CastEltSize / DstEltSize;
4099 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4100 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4106 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4107 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4109 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4112 ES->eraseFromParent();
4120 LLT DstTy = MRI.getType(DstReg);
4128 if (MemSizeInBits != MemStoreSizeInBits) {
4145 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4149 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4150 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4152 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4155 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4157 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4160 if (DstTy != LoadTy)
4168 if (
MIRBuilder.getDataLayout().isBigEndian())
4186 uint64_t LargeSplitSize, SmallSplitSize;
4191 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4198 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4201 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4212 if (Alignment.
value() * 8 > MemSizeInBits &&
4217 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4234 LLT PtrTy = MRI.getType(PtrReg);
4237 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4241 LargeSplitSize / 8);
4242 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4243 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4245 SmallPtr, *SmallMMO);
4247 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4248 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4250 if (AnyExtTy == DstTy)
4251 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4253 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4257 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4277 LLT SrcTy = MRI.getType(SrcReg);
4285 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4291 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4293 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4297 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4301 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4316 uint64_t LargeSplitSize, SmallSplitSize;
4323 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4326 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4335 if (SrcTy.isPointer()) {
4337 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4340 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4343 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4344 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4347 LLT PtrTy = MRI.getType(PtrReg);
4350 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4356 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4357 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4366 LLT SrcTy = MRI.getType(SrcReg);
4372 assert(SrcTy.isVector() &&
"Expect a vector store type");
4379 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4383 auto Elt =
MIRBuilder.buildExtractVectorElement(
4384 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4385 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4386 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4392 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4393 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4397 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4408 switch (
MI.getOpcode()) {
4409 case TargetOpcode::G_LOAD: {
4427 case TargetOpcode::G_STORE: {
4443 case TargetOpcode::G_SELECT: {
4447 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4449 dbgs() <<
"bitcast action not implemented for vector select\n");
4460 case TargetOpcode::G_AND:
4461 case TargetOpcode::G_OR:
4462 case TargetOpcode::G_XOR: {
4470 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4472 case TargetOpcode::G_INSERT_VECTOR_ELT:
4474 case TargetOpcode::G_CONCAT_VECTORS:
4476 case TargetOpcode::G_SHUFFLE_VECTOR:
4478 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4480 case TargetOpcode::G_INSERT_SUBVECTOR:
4488void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4498 switch(
MI.getOpcode()) {
4501 case TargetOpcode::G_FCONSTANT:
4503 case TargetOpcode::G_BITCAST:
4505 case TargetOpcode::G_SREM:
4506 case TargetOpcode::G_UREM: {
4507 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4509 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4510 {MI.getOperand(1), MI.getOperand(2)});
4512 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4514 MI.eraseFromParent();
4517 case TargetOpcode::G_SADDO:
4518 case TargetOpcode::G_SSUBO:
4520 case TargetOpcode::G_SADDE:
4522 case TargetOpcode::G_SSUBE:
4524 case TargetOpcode::G_UMULH:
4525 case TargetOpcode::G_SMULH:
4527 case TargetOpcode::G_SMULO:
4528 case TargetOpcode::G_UMULO: {
4531 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4532 LLT Ty = MRI.getType(Res);
4534 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4535 ? TargetOpcode::G_SMULH
4536 : TargetOpcode::G_UMULH;
4540 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4541 MI.removeOperand(1);
4544 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4552 if (Opcode == TargetOpcode::G_SMULH) {
4553 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4554 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4561 case TargetOpcode::G_FNEG: {
4562 auto [Res, SubByReg] =
MI.getFirst2Regs();
4563 LLT Ty = MRI.getType(Res);
4567 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4568 MI.eraseFromParent();
4571 case TargetOpcode::G_FSUB:
4572 case TargetOpcode::G_STRICT_FSUB: {
4573 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4574 LLT Ty = MRI.getType(Res);
4579 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4580 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4584 MI.eraseFromParent();
4587 case TargetOpcode::G_FMAD:
4589 case TargetOpcode::G_FFLOOR:
4591 case TargetOpcode::G_LROUND:
4592 case TargetOpcode::G_LLROUND: {
4595 LLT SrcTy = MRI.getType(SrcReg);
4596 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4599 MI.eraseFromParent();
4602 case TargetOpcode::G_INTRINSIC_ROUND:
4604 case TargetOpcode::G_FRINT: {
4607 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4610 case TargetOpcode::G_INTRINSIC_LRINT:
4611 case TargetOpcode::G_INTRINSIC_LLRINT: {
4614 LLT SrcTy = MRI.getType(SrcReg);
4616 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4618 MI.eraseFromParent();
4621 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4622 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4623 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4624 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4625 **
MI.memoperands_begin());
4627 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4628 MI.eraseFromParent();
4631 case TargetOpcode::G_LOAD:
4632 case TargetOpcode::G_SEXTLOAD:
4633 case TargetOpcode::G_ZEXTLOAD:
4635 case TargetOpcode::G_STORE:
4637 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4638 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4639 case TargetOpcode::G_CTLZ:
4640 case TargetOpcode::G_CTTZ:
4641 case TargetOpcode::G_CTPOP:
4644 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4646 Register NewRes = MRI.cloneVirtualRegister(Res);
4653 MI.eraseFromParent();
4657 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4658 const LLT CondTy = MRI.getType(CarryOut);
4659 const LLT Ty = MRI.getType(Res);
4661 Register NewRes = MRI.cloneVirtualRegister(Res);
4664 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4670 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4671 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4678 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4683 MI.eraseFromParent();
4687 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4692 MI.eraseFromParent();
4696 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4697 const LLT CondTy = MRI.getType(BorrowOut);
4698 const LLT Ty = MRI.getType(Res);
4701 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4707 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4708 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4715 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4716 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4718 MI.eraseFromParent();
4754 case G_MERGE_VALUES:
4756 case G_UNMERGE_VALUES:
4758 case TargetOpcode::G_SEXT_INREG: {
4759 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4760 int64_t SizeInBits =
MI.getOperand(2).getImm();
4762 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4763 LLT DstTy = MRI.getType(DstReg);
4764 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4767 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4768 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4769 MI.eraseFromParent();
4772 case G_EXTRACT_VECTOR_ELT:
4773 case G_INSERT_VECTOR_ELT:
4775 case G_SHUFFLE_VECTOR:
4777 case G_VECTOR_COMPRESS:
4779 case G_DYN_STACKALLOC:
4783 case G_STACKRESTORE:
4793 case G_READ_REGISTER:
4794 case G_WRITE_REGISTER:
4801 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4802 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4808 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4813 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4824 bool IsSigned =
MI.getOpcode() == G_ABDS;
4825 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4826 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4827 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4851 case G_MEMCPY_INLINE:
4852 return lowerMemcpyInline(
MI);
4863 case G_ATOMICRMW_SUB: {
4864 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4865 const LLT ValTy = MRI.getType(Val);
4869 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4870 MI.eraseFromParent();
4893 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4897 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4903 Align StackTypeAlign =
4910 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4911 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4916 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4928 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4931 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4942 "Converting bits to bytes lost precision");
4948 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4949 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4951 if (IdxTy != MRI.getType(Index))
4952 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4957 LLT PtrTy = MRI.getType(VecPtr);
4958 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4966 std::initializer_list<unsigned> NonVecOpIndices) {
4967 if (
MI.getNumMemOperands() != 0)
4970 LLT VecTy =
MRI.getType(
MI.getReg(0));
4984 if (!Ty.isVector()) {
4990 if (Ty.getNumElements() != NumElts)
5005 assert(Ty.isVector() &&
"Expected vector type");
5008 int NumParts, NumLeftover;
5009 std::tie(NumParts, NumLeftover) =
5012 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5013 for (
int i = 0; i < NumParts; ++i) {
5018 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5027 for (
unsigned i = 0; i <
N; ++i) {
5029 Ops.push_back(
Op.getReg());
5030 else if (
Op.isImm())
5031 Ops.push_back(
Op.getImm());
5032 else if (
Op.isPredicate())
5054 std::initializer_list<unsigned> NonVecOpIndices) {
5056 "Non-compatible opcode or not specified non-vector operands");
5057 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5059 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5060 unsigned NumDefs =
MI.getNumDefs();
5068 for (
unsigned i = 0; i < NumDefs; ++i) {
5069 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5077 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5078 ++UseIdx, ++UseNo) {
5081 MI.getOperand(UseIdx));
5090 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5094 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5096 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5097 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5100 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5101 Uses.push_back(InputOpsPieces[InputNo][i]);
5104 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5105 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5110 for (
unsigned i = 0; i < NumDefs; ++i)
5111 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5113 for (
unsigned i = 0; i < NumDefs; ++i)
5114 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5117 MI.eraseFromParent();
5124 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5126 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5127 unsigned NumDefs =
MI.getNumDefs();
5131 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5136 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5137 UseIdx += 2, ++UseNo) {
5145 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5147 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5148 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5150 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5153 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5154 Phi.addUse(InputOpsPieces[j][i]);
5155 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5165 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5167 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5170 MI.eraseFromParent();
5178 const int NumDst =
MI.getNumOperands() - 1;
5179 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5180 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5181 LLT SrcTy = MRI.getType(SrcReg);
5183 if (TypeIdx != 1 || NarrowTy == DstTy)
5190 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5193 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5207 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5208 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5209 const int PartsPerUnmerge = NumDst / NumUnmerge;
5211 for (
int I = 0;
I != NumUnmerge; ++
I) {
5212 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5214 for (
int J = 0; J != PartsPerUnmerge; ++J)
5215 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5216 MIB.addUse(Unmerge.getReg(
I));
5219 MI.eraseFromParent();
5226 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5230 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5232 if (NarrowTy == SrcTy)
5240 assert(SrcTy.isVector() &&
"Expected vector types");
5242 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5256 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5257 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5258 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5264 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5265 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5266 ++i,
Offset += NumNarrowTyElts) {
5269 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5272 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5273 MI.eraseFromParent();
5277 assert(TypeIdx == 0 &&
"Bad type index");
5278 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5293 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5294 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5296 for (
unsigned i = 0; i < NumParts; ++i) {
5298 for (
unsigned j = 0; j < NumElts; ++j)
5299 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5301 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5304 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5305 MI.eraseFromParent();
5313 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5315 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5317 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5319 InsertVal =
MI.getOperand(2).getReg();
5321 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5322 LLT VecTy = MRI.getType(SrcVec);
5328 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5332 MI.eraseFromParent();
5341 SplitPieces[IdxVal] = InsertVal;
5342 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5344 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5348 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5351 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5352 TargetOpcode::G_ANYEXT);
5356 LLT IdxTy = MRI.getType(Idx);
5357 int64_t PartIdx = IdxVal / NewNumElts;
5359 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5362 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5365 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5366 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5367 VecParts[PartIdx] = InsertPart.getReg(0);
5371 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5373 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5377 MI.eraseFromParent();
5397 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5409 LLT ValTy = MRI.getType(ValReg);
5418 int NumLeftover = -1;
5424 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5426 NumParts = NarrowRegs.
size();
5427 NumLeftover = NarrowLeftoverRegs.
size();
5434 LLT PtrTy = MRI.getType(AddrReg);
5437 unsigned TotalSize = ValTy.getSizeInBits();
5444 auto MMO = LdStMI.
getMMO();
5446 unsigned NumParts,
unsigned Offset) ->
unsigned {
5449 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5451 unsigned ByteOffset =
Offset / 8;
5454 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5461 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5462 ValRegs.push_back(Dst);
5463 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5465 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5474 unsigned HandledOffset =
5475 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5479 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5482 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5483 LeftoverTy, NarrowLeftoverRegs);
5497 switch (
MI.getOpcode()) {
5498 case G_IMPLICIT_DEF:
5514 case G_FCANONICALIZE:
5531 case G_INTRINSIC_LRINT:
5532 case G_INTRINSIC_LLRINT:
5533 case G_INTRINSIC_ROUND:
5534 case G_INTRINSIC_ROUNDEVEN:
5537 case G_INTRINSIC_TRUNC:
5565 case G_FMINNUM_IEEE:
5566 case G_FMAXNUM_IEEE:
5588 case G_CTLZ_ZERO_UNDEF:
5590 case G_CTTZ_ZERO_UNDEF:
5606 case G_ADDRSPACE_CAST:
5619 case G_STRICT_FLDEXP:
5628 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5633 case G_UNMERGE_VALUES:
5635 case G_BUILD_VECTOR:
5636 assert(TypeIdx == 0 &&
"not a vector type index");
5638 case G_CONCAT_VECTORS:
5642 case G_EXTRACT_VECTOR_ELT:
5643 case G_INSERT_VECTOR_ELT:
5652 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5653 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5655 case G_SHUFFLE_VECTOR:
5661 case G_INTRINSIC_FPTRUNC_ROUND:
5671 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5672 "Not a bitcast operation");
5677 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5679 unsigned NewElemCount =
5682 if (NewElemCount == 1) {
5685 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5691 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5700 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5701 MI.eraseFromParent();
5707 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5711 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5712 MI.getFirst3RegLLTs();
5715 if (DstTy != Src1Ty)
5717 if (DstTy != Src2Ty)
5732 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5748 unsigned InputUsed[2] = {-1U, -1U};
5749 unsigned FirstMaskIdx =
High * NewElts;
5750 bool UseBuildVector =
false;
5751 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5753 int Idx = Mask[FirstMaskIdx + MaskOffset];
5758 if (
Input >= std::size(Inputs)) {
5765 Idx -=
Input * NewElts;
5769 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5770 if (InputUsed[OpNo] ==
Input) {
5773 }
else if (InputUsed[OpNo] == -1U) {
5775 InputUsed[OpNo] =
Input;
5780 if (OpNo >= std::size(InputUsed)) {
5783 UseBuildVector =
true;
5788 Ops.push_back(Idx + OpNo * NewElts);
5791 if (UseBuildVector) {
5796 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5798 int Idx = Mask[FirstMaskIdx + MaskOffset];
5803 if (
Input >= std::size(Inputs)) {
5810 Idx -=
Input * NewElts;
5814 .buildExtractVectorElement(
5815 EltTy, Inputs[
Input],
5821 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5822 }
else if (InputUsed[0] == -1U) {
5824 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5825 }
else if (NewElts == 1) {
5826 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
5828 Register Op0 = Inputs[InputUsed[0]];
5832 : Inputs[InputUsed[1]];
5834 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5841 MI.eraseFromParent();
5854 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5860 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5863 const unsigned NumParts =
5865 : SrcTy.getNumElements();
5869 if (DstTy != NarrowTy)
5875 unsigned NumPartsLeft = NumParts;
5876 while (NumPartsLeft > 1) {
5877 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5880 .buildInstr(ScalarOpc, {NarrowTy},
5881 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5884 SplitSrcs = PartialResults;
5885 PartialResults.
clear();
5886 NumPartsLeft = SplitSrcs.
size();
5890 MI.eraseFromParent();
5895 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5896 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5899 MI.eraseFromParent();
5903 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5905 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5913 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5916 Register Acc = PartialReductions[0];
5917 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5918 if (Part == NumParts - 1) {
5920 {Acc, PartialReductions[Part]});
5923 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5927 MI.eraseFromParent();
5933 unsigned int TypeIdx,
5935 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5936 MI.getFirst3RegLLTs();
5937 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5941 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5942 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5943 "Unexpected vecreduce opcode");
5944 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5945 ? TargetOpcode::G_FADD
5946 : TargetOpcode::G_FMUL;
5949 unsigned NumParts = SrcTy.getNumElements();
5952 for (
unsigned i = 0; i < NumParts; i++)
5953 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5957 MI.eraseFromParent();
5964 unsigned ScalarOpc) {
5972 while (SplitSrcs.
size() > 1) {
5974 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
5982 SplitSrcs = std::move(PartialRdxs);
5986 MI.getOperand(1).setReg(SplitSrcs[0]);
5993 const LLT HalfTy,
const LLT AmtTy) {
5995 Register InL = MRI.createGenericVirtualRegister(HalfTy);
5996 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6000 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6001 MI.eraseFromParent();
6007 unsigned VTBits = 2 * NVTBits;
6010 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6011 if (Amt.
ugt(VTBits)) {
6013 }
else if (Amt.
ugt(NVTBits)) {
6016 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6017 }
else if (Amt == NVTBits) {
6025 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6028 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6029 if (Amt.
ugt(VTBits)) {
6031 }
else if (Amt.
ugt(NVTBits)) {
6033 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6035 }
else if (Amt == NVTBits) {
6039 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6041 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6043 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6049 if (Amt.
ugt(VTBits)) {
6051 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6052 }
else if (Amt.
ugt(NVTBits)) {
6054 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6056 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6057 }
else if (Amt == NVTBits) {
6060 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6062 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6064 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6066 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6073 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6074 MI.eraseFromParent();
6090 LLT DstTy = MRI.getType(DstReg);
6095 LLT ShiftAmtTy = MRI.getType(Amt);
6097 if (DstEltSize % 2 != 0)
6113 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6124 const unsigned NewBitSize = DstEltSize / 2;
6136 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6138 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6139 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6142 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6143 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6145 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6150 switch (
MI.getOpcode()) {
6151 case TargetOpcode::G_SHL: {
6153 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6155 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6156 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6157 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6160 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6161 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6163 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6165 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6167 ResultRegs[0] =
Lo.getReg(0);
6168 ResultRegs[1] =
Hi.getReg(0);
6171 case TargetOpcode::G_LSHR:
6172 case TargetOpcode::G_ASHR: {
6174 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6176 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6177 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6178 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6182 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6185 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6186 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6188 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6192 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6194 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6196 ResultRegs[0] =
Lo.getReg(0);
6197 ResultRegs[1] =
Hi.getReg(0);
6204 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6205 MI.eraseFromParent();
6214 LLT TargetTy,
LLT ShiftAmtTy) {
6217 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6219 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6220 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6221 const bool NeedsInterWordShift = ShiftBits != 0;
6224 case TargetOpcode::G_SHL: {
6227 if (PartIdx < ShiftWords)
6230 unsigned SrcIdx = PartIdx - ShiftWords;
6231 if (!NeedsInterWordShift)
6232 return SrcParts[SrcIdx];
6237 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6241 return Hi.getReg(0);
6244 case TargetOpcode::G_LSHR: {
6245 unsigned SrcIdx = PartIdx + ShiftWords;
6246 if (SrcIdx >= NumParts)
6248 if (!NeedsInterWordShift)
6249 return SrcParts[SrcIdx];
6253 if (SrcIdx + 1 < NumParts) {
6254 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6258 return Lo.getReg(0);
6261 case TargetOpcode::G_ASHR: {
6263 unsigned SrcIdx = PartIdx + ShiftWords;
6264 if (SrcIdx >= NumParts)
6266 if (!NeedsInterWordShift)
6267 return SrcParts[SrcIdx];
6272 (SrcIdx == NumParts - 1)
6276 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6298 unsigned MainOpcode =
6299 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6303 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6312 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6313 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6315 auto IsZeroBitShift =
6323 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6324 : TargetOpcode::G_SHL;
6327 auto TargetBitsConst =
6329 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6334 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6339 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6341 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6345 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6358 LLT DstTy = MRI.getType(DstReg);
6362 const unsigned NumParts = DstBits / TargetBits;
6364 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6374 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6375 MI.eraseFromParent();
6380 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6381 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6387 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6391 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6394 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6395 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6399 for (
unsigned I = 0;
I < NumParts; ++
I)
6401 Params, TargetTy, ShiftAmtTy);
6403 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6404 MI.eraseFromParent();
6413 LLT DstTy = MRI.getType(DstReg);
6414 LLT ShiftAmtTy = MRI.getType(AmtReg);
6418 const unsigned NumParts = DstBits / TargetBits;
6420 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6437 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6449 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6450 auto TargetBitsLog2Const =
6451 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6452 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6455 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6457 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6465 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6466 auto TargetBitsMinusOneConst =
6467 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6469 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6470 TargetBitsMinusOneConst)
6473 FillValue = ZeroReg;
6481 for (
unsigned I = 0;
I < NumParts; ++
I) {
6483 Register InBoundsResult = FillValue;
6493 for (
unsigned K = 0; K < NumParts; ++K) {
6494 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6496 WordShift, WordShiftKConst);
6508 switch (
MI.getOpcode()) {
6509 case TargetOpcode::G_SHL:
6510 MainSrcIdx = (int)
I - (
int)K;
6511 CarrySrcIdx = MainSrcIdx - 1;
6513 case TargetOpcode::G_LSHR:
6514 case TargetOpcode::G_ASHR:
6515 MainSrcIdx = (int)
I + (
int)K;
6516 CarrySrcIdx = MainSrcIdx + 1;
6524 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6525 Register MainOp = SrcParts[MainSrcIdx];
6529 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6530 CarryOp = SrcParts[CarrySrcIdx];
6531 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6532 CarrySrcIdx >= (
int)NumParts)
6533 CarryOp = FillValue;
6539 ResultForK = FillValue;
6545 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6552 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6556 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6557 MI.eraseFromParent();
6564 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6567 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6582 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6587 "getNeutralElementForVecReduce called with invalid opcode!");
6588 case TargetOpcode::G_VECREDUCE_ADD:
6589 case TargetOpcode::G_VECREDUCE_OR:
6590 case TargetOpcode::G_VECREDUCE_XOR:
6591 case TargetOpcode::G_VECREDUCE_UMAX:
6593 case TargetOpcode::G_VECREDUCE_MUL:
6595 case TargetOpcode::G_VECREDUCE_AND:
6596 case TargetOpcode::G_VECREDUCE_UMIN:
6599 case TargetOpcode::G_VECREDUCE_SMAX:
6602 case TargetOpcode::G_VECREDUCE_SMIN:
6605 case TargetOpcode::G_VECREDUCE_FADD:
6607 case TargetOpcode::G_VECREDUCE_FMUL:
6609 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6610 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6611 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6612 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6620 unsigned Opc =
MI.getOpcode();
6622 case TargetOpcode::G_IMPLICIT_DEF:
6623 case TargetOpcode::G_LOAD: {
6631 case TargetOpcode::G_STORE:
6638 case TargetOpcode::G_AND:
6639 case TargetOpcode::G_OR:
6640 case TargetOpcode::G_XOR:
6641 case TargetOpcode::G_ADD:
6642 case TargetOpcode::G_SUB:
6643 case TargetOpcode::G_MUL:
6644 case TargetOpcode::G_FADD:
6645 case TargetOpcode::G_FSUB:
6646 case TargetOpcode::G_FMUL:
6647 case TargetOpcode::G_FDIV:
6648 case TargetOpcode::G_FCOPYSIGN:
6649 case TargetOpcode::G_UADDSAT:
6650 case TargetOpcode::G_USUBSAT:
6651 case TargetOpcode::G_SADDSAT:
6652 case TargetOpcode::G_SSUBSAT:
6653 case TargetOpcode::G_SMIN:
6654 case TargetOpcode::G_SMAX:
6655 case TargetOpcode::G_UMIN:
6656 case TargetOpcode::G_UMAX:
6657 case TargetOpcode::G_FMINNUM:
6658 case TargetOpcode::G_FMAXNUM:
6659 case TargetOpcode::G_FMINNUM_IEEE:
6660 case TargetOpcode::G_FMAXNUM_IEEE:
6661 case TargetOpcode::G_FMINIMUM:
6662 case TargetOpcode::G_FMAXIMUM:
6663 case TargetOpcode::G_FMINIMUMNUM:
6664 case TargetOpcode::G_FMAXIMUMNUM:
6665 case TargetOpcode::G_STRICT_FADD:
6666 case TargetOpcode::G_STRICT_FSUB:
6667 case TargetOpcode::G_STRICT_FMUL:
6668 case TargetOpcode::G_SHL:
6669 case TargetOpcode::G_ASHR:
6670 case TargetOpcode::G_LSHR: {
6678 case TargetOpcode::G_FMA:
6679 case TargetOpcode::G_STRICT_FMA:
6680 case TargetOpcode::G_FSHR:
6681 case TargetOpcode::G_FSHL: {
6690 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6691 case TargetOpcode::G_EXTRACT:
6698 case TargetOpcode::G_INSERT:
6699 case TargetOpcode::G_INSERT_VECTOR_ELT:
6700 case TargetOpcode::G_FREEZE:
6701 case TargetOpcode::G_FNEG:
6702 case TargetOpcode::G_FABS:
6703 case TargetOpcode::G_FSQRT:
6704 case TargetOpcode::G_FCEIL:
6705 case TargetOpcode::G_FFLOOR:
6706 case TargetOpcode::G_FNEARBYINT:
6707 case TargetOpcode::G_FRINT:
6708 case TargetOpcode::G_INTRINSIC_ROUND:
6709 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6710 case TargetOpcode::G_INTRINSIC_TRUNC:
6711 case TargetOpcode::G_BITREVERSE:
6712 case TargetOpcode::G_BSWAP:
6713 case TargetOpcode::G_FCANONICALIZE:
6714 case TargetOpcode::G_SEXT_INREG:
6715 case TargetOpcode::G_ABS:
6716 case TargetOpcode::G_CTLZ:
6717 case TargetOpcode::G_CTPOP:
6725 case TargetOpcode::G_SELECT: {
6726 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6728 if (!CondTy.isScalar() ||
6734 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6736 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6741 if (CondTy.isVector())
6751 case TargetOpcode::G_UNMERGE_VALUES:
6753 case TargetOpcode::G_PHI:
6755 case TargetOpcode::G_SHUFFLE_VECTOR:
6757 case TargetOpcode::G_BUILD_VECTOR: {
6759 for (
auto Op :
MI.uses()) {
6767 MIRBuilder.buildDeleteTrailingVectorElements(
6768 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6769 MI.eraseFromParent();
6772 case TargetOpcode::G_SEXT:
6773 case TargetOpcode::G_ZEXT:
6774 case TargetOpcode::G_ANYEXT:
6775 case TargetOpcode::G_TRUNC:
6776 case TargetOpcode::G_FPTRUNC:
6777 case TargetOpcode::G_FPEXT:
6778 case TargetOpcode::G_FPTOSI:
6779 case TargetOpcode::G_FPTOUI:
6780 case TargetOpcode::G_FPTOSI_SAT:
6781 case TargetOpcode::G_FPTOUI_SAT:
6782 case TargetOpcode::G_SITOFP:
6783 case TargetOpcode::G_UITOFP: {
6791 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6795 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6803 case TargetOpcode::G_ICMP:
6804 case TargetOpcode::G_FCMP: {
6813 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6818 case TargetOpcode::G_BITCAST: {
6822 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6823 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6839 case TargetOpcode::G_VECREDUCE_FADD:
6840 case TargetOpcode::G_VECREDUCE_FMUL:
6841 case TargetOpcode::G_VECREDUCE_ADD:
6842 case TargetOpcode::G_VECREDUCE_MUL:
6843 case TargetOpcode::G_VECREDUCE_AND:
6844 case TargetOpcode::G_VECREDUCE_OR:
6845 case TargetOpcode::G_VECREDUCE_XOR:
6846 case TargetOpcode::G_VECREDUCE_SMAX:
6847 case TargetOpcode::G_VECREDUCE_SMIN:
6848 case TargetOpcode::G_VECREDUCE_UMAX:
6849 case TargetOpcode::G_VECREDUCE_UMIN: {
6850 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6852 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6853 auto NeutralElement = getNeutralElementForVecReduce(
6859 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6860 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6861 NeutralElement, Idx);
6865 MO.
setReg(NewVec.getReg(0));
6877 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6879 unsigned MaskNumElts = Mask.size();
6880 unsigned SrcNumElts = SrcTy.getNumElements();
6883 if (MaskNumElts == SrcNumElts)
6886 if (MaskNumElts < SrcNumElts) {
6894 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6895 MI.getOperand(1).getReg(),
6896 MI.getOperand(2).getReg(), NewMask);
6897 MI.eraseFromParent();
6902 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6903 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6911 MOps1[0] =
MI.getOperand(1).getReg();
6912 MOps2[0] =
MI.getOperand(2).getReg();
6914 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6915 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6919 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6921 if (Idx >=
static_cast<int>(SrcNumElts))
6922 Idx += PaddedMaskNumElts - SrcNumElts;
6927 if (MaskNumElts != PaddedMaskNumElts) {
6929 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6932 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6934 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6939 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6942 MI.eraseFromParent();
6948 unsigned int TypeIdx,
LLT MoreTy) {
6949 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6951 unsigned NumElts = DstTy.getNumElements();
6954 if (DstTy.isVector() && Src1Ty.isVector() &&
6955 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6963 if (DstTy != Src1Ty || DstTy != Src2Ty)
6971 for (
unsigned I = 0;
I != NumElts; ++
I) {
6973 if (Idx <
static_cast<int>(NumElts))
6976 NewMask[
I] = Idx - NumElts + WidenNumElts;
6980 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6981 MI.getOperand(1).getReg(),
6982 MI.getOperand(2).getReg(), NewMask);
6983 MI.eraseFromParent();
6992 unsigned SrcParts = Src1Regs.
size();
6993 unsigned DstParts = DstRegs.
size();
6995 unsigned DstIdx = 0;
6997 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
6998 DstRegs[DstIdx] = FactorSum;
7003 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7005 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7006 i <= std::min(DstIdx, SrcParts - 1); ++i) {
7008 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7012 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7013 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7015 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7025 if (DstIdx != DstParts - 1) {
7026 MachineInstrBuilder Uaddo =
7027 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
7028 FactorSum = Uaddo.
getReg(0);
7029 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7030 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7031 MachineInstrBuilder Uaddo =
7032 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
7033 FactorSum = Uaddo.
getReg(0);
7034 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7035 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7039 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7040 for (
unsigned i = 2; i < Factors.
size(); ++i)
7041 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7044 CarrySumPrevDstIdx = CarrySum;
7045 DstRegs[DstIdx] = FactorSum;
7057 LLT DstType = MRI.getType(DstReg);
7059 if (DstType.isVector())
7062 unsigned Opcode =
MI.getOpcode();
7063 unsigned OpO, OpE, OpF;
7065 case TargetOpcode::G_SADDO:
7066 case TargetOpcode::G_SADDE:
7067 case TargetOpcode::G_UADDO:
7068 case TargetOpcode::G_UADDE:
7069 case TargetOpcode::G_ADD:
7070 OpO = TargetOpcode::G_UADDO;
7071 OpE = TargetOpcode::G_UADDE;
7072 OpF = TargetOpcode::G_UADDE;
7073 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7074 OpF = TargetOpcode::G_SADDE;
7076 case TargetOpcode::G_SSUBO:
7077 case TargetOpcode::G_SSUBE:
7078 case TargetOpcode::G_USUBO:
7079 case TargetOpcode::G_USUBE:
7080 case TargetOpcode::G_SUB:
7081 OpO = TargetOpcode::G_USUBO;
7082 OpE = TargetOpcode::G_USUBE;
7083 OpF = TargetOpcode::G_USUBE;
7084 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7085 OpF = TargetOpcode::G_SSUBE;
7092 unsigned NumDefs =
MI.getNumExplicitDefs();
7093 Register Src1 =
MI.getOperand(NumDefs).getReg();
7094 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7097 CarryDst =
MI.getOperand(1).getReg();
7098 if (
MI.getNumOperands() == NumDefs + 3)
7099 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7101 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7102 LLT LeftoverTy, DummyTy;
7104 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7109 int NarrowParts = Src1Regs.
size();
7110 Src1Regs.
append(Src1Left);
7111 Src2Regs.
append(Src2Left);
7114 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7116 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7119 if (i == e - 1 && CarryDst)
7120 CarryOut = CarryDst;
7122 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7125 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7126 {Src1Regs[i], Src2Regs[i]});
7127 }
else if (i == e - 1) {
7128 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7129 {Src1Regs[i], Src2Regs[i], CarryIn});
7131 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7132 {Src1Regs[i], Src2Regs[i], CarryIn});
7138 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7139 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7140 ArrayRef(DstRegs).drop_front(NarrowParts));
7142 MI.eraseFromParent();
7148 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7150 LLT Ty = MRI.getType(DstReg);
7154 unsigned Size = Ty.getSizeInBits();
7156 if (
Size % NarrowSize != 0)
7159 unsigned NumParts =
Size / NarrowSize;
7160 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7161 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7167 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7171 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7172 MI.eraseFromParent();
7182 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7185 LLT SrcTy = MRI.getType(Src);
7196 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7209 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7212 if (SizeOp1 % NarrowSize != 0)
7214 int NumParts = SizeOp1 / NarrowSize;
7217 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7221 uint64_t OpStart =
MI.getOperand(2).getImm();
7222 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7223 for (
int i = 0; i < NumParts; ++i) {
7224 unsigned SrcStart = i * NarrowSize;
7226 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7229 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7237 int64_t ExtractOffset;
7239 if (OpStart < SrcStart) {
7241 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7243 ExtractOffset = OpStart - SrcStart;
7244 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7248 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7250 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7251 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7258 if (MRI.getType(DstReg).isVector())
7259 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7260 else if (DstRegs.
size() > 1)
7261 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7264 MI.eraseFromParent();
7276 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7278 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7281 SrcRegs.
append(LeftoverRegs);
7285 uint64_t OpStart =
MI.getOperand(3).getImm();
7286 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7287 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7288 unsigned DstStart =
I * NarrowSize;
7290 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7298 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7300 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7304 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7312 int64_t ExtractOffset, InsertOffset;
7314 if (OpStart < DstStart) {
7316 ExtractOffset = DstStart - OpStart;
7317 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7319 InsertOffset = OpStart - DstStart;
7322 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7326 if (ExtractOffset != 0 || SegSize != OpSize) {
7328 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7329 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7332 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7333 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7341 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7344 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7346 MI.eraseFromParent();
7354 LLT DstTy = MRI.getType(DstReg);
7356 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7362 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7363 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7367 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7368 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7371 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7372 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7373 {Src0Regs[I], Src1Regs[I]});
7377 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7380 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7381 DstLeftoverRegs.
push_back(Inst.getReg(0));
7384 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7385 LeftoverTy, DstLeftoverRegs);
7387 MI.eraseFromParent();
7397 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7399 LLT DstTy = MRI.getType(DstReg);
7404 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7405 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7406 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7408 MI.eraseFromParent();
7418 Register CondReg =
MI.getOperand(1).getReg();
7419 LLT CondTy = MRI.getType(CondReg);
7424 LLT DstTy = MRI.getType(DstReg);
7430 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7431 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7435 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7436 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7439 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7441 CondReg, Src1Regs[
I], Src2Regs[
I]);
7445 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7447 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7451 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7452 LeftoverTy, DstLeftoverRegs);
7454 MI.eraseFromParent();
7464 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7467 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7468 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7471 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7473 auto C_0 =
B.buildConstant(NarrowTy, 0);
7475 UnmergeSrc.getReg(1), C_0);
7476 auto LoCTLZ = IsUndef ?
7477 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7478 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7479 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7480 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7481 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7482 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7484 MI.eraseFromParent();
7497 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7500 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7501 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7504 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7506 auto C_0 =
B.buildConstant(NarrowTy, 0);
7508 UnmergeSrc.getReg(0), C_0);
7509 auto HiCTTZ = IsUndef ?
7510 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7511 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7512 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7513 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7514 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7515 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7517 MI.eraseFromParent();
7530 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7533 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7534 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7536 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7537 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7538 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7540 MI.eraseFromParent();
7555 LLT ExpTy = MRI.getType(ExpReg);
7560 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7561 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7562 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7563 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7565 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7567 MI.getOperand(2).setReg(Trunc.getReg(0));
7574 unsigned Opc =
MI.getOpcode();
7577 auto QAction = LI.getAction(Q).Action;
7583 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7586 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7590 case TargetOpcode::G_CTLZ: {
7591 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7592 unsigned Len = SrcTy.getSizeInBits();
7594 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7596 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7597 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7600 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7601 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7602 MI.eraseFromParent();
7618 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7619 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7622 Op = MIBOp.getReg(0);
7627 MI.eraseFromParent();
7630 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7633 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7637 case TargetOpcode::G_CTTZ: {
7638 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7640 unsigned Len = SrcTy.getSizeInBits();
7641 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7644 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7645 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7648 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7649 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7650 MI.eraseFromParent();
7657 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7658 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7660 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7661 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7662 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7663 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7666 MI.eraseFromParent();
7670 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7671 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7675 case TargetOpcode::G_CTPOP: {
7677 LLT Ty = MRI.getType(SrcReg);
7678 unsigned Size = Ty.getSizeInBits();
7686 auto C_1 =
B.buildConstant(Ty, 1);
7687 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7689 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7690 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7691 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7695 auto C_2 =
B.buildConstant(Ty, 2);
7696 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7698 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7699 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7700 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7701 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7708 auto C_4 =
B.buildConstant(Ty, 4);
7709 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7710 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7712 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7713 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7715 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7721 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7723 auto IsMulSupported = [
this](
const LLT Ty) {
7724 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7727 if (IsMulSupported(Ty)) {
7728 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7729 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7731 auto ResTmp = B8Count;
7732 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7733 auto ShiftC =
B.buildConstant(Ty, Shift);
7734 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7735 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7737 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7739 MI.eraseFromParent();
7760 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7761 LLT Ty = MRI.getType(Dst);
7762 LLT ShTy = MRI.getType(Z);
7769 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7770 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7775 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7776 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7780 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7793 MI.eraseFromParent();
7799 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7800 LLT Ty = MRI.getType(Dst);
7801 LLT ShTy = MRI.getType(Z);
7804 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7814 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7815 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7816 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7817 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7818 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7822 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7825 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7828 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7830 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7831 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7832 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7835 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7837 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7839 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7842 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7843 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7848 MI.eraseFromParent();
7859 LLT Ty = MRI.getType(Dst);
7860 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7862 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7863 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7866 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7867 return lowerFunnelShiftAsShifts(
MI);
7871 if (Result == UnableToLegalize)
7872 return lowerFunnelShiftAsShifts(
MI);
7877 auto [Dst, Src] =
MI.getFirst2Regs();
7878 LLT DstTy = MRI.getType(Dst);
7879 LLT SrcTy = MRI.getType(Src);
7883 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7891 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7895 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7899 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7904 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7905 {UnmergeSrc.getReg(0)});
7906 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7907 {UnmergeSrc.getReg(1)});
7910 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7912 MI.eraseFromParent();
7929 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7933 LLT DstTy = MRI.getType(DstReg);
7934 LLT SrcTy = MRI.getType(SrcReg);
7942 SrcTy.getElementCount().divideCoefficientBy(2));
7955 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7967 MI.eraseFromParent();
7976 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7977 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
7978 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7979 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7980 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
7981 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
7982 MI.eraseFromParent();
7987 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7989 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
7990 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7995 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7996 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
7998 return lowerRotateWithReverseRotate(
MI);
8001 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8002 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8003 bool IsFShLegal =
false;
8004 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8005 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8009 MI.eraseFromParent();
8014 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8017 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8022 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8023 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8024 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8030 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8031 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8033 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8039 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8040 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8042 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8044 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8048 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
8049 MI.eraseFromParent();
8057 auto [Dst, Src] =
MI.getFirst2Regs();
8062 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8090 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8103 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8107 MI.eraseFromParent();
8115 auto [Dst, Src] =
MI.getFirst2Regs();
8120 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8133 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8135 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8140 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8142 MI.eraseFromParent();
8150 auto [Dst, Src] =
MI.getFirst2Regs();
8154 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8165 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8166 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8168 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8175 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8176 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8177 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8179 MI.eraseFromParent();
8189 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8195 MI.eraseFromParent();
8200 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8203 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8204 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8205 MIRBuilder.buildSelect(Dst, Src, True, False);
8206 MI.eraseFromParent();
8210 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8230 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8237 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8238 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8239 MIRBuilder.buildSelect(Dst, Src, True, False);
8240 MI.eraseFromParent();
8244 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8267 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8268 MI.eraseFromParent();
8276 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8280 if (SrcTy !=
S64 && SrcTy !=
S32)
8282 if (DstTy !=
S32 && DstTy !=
S64)
8309 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8311 MI.eraseFromParent();
8316 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8321 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8328 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8330 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8331 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8333 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8334 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8336 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8338 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8339 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8340 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8343 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8344 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8345 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8347 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8350 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8355 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8356 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8362 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8364 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8365 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8367 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8372 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8373 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8375 MI.eraseFromParent();
8381 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8383 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8384 unsigned SatWidth = DstTy.getScalarSizeInBits();
8388 APInt MinInt, MaxInt;
8411 if (AreExactFloatBounds) {
8413 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8415 SrcTy.changeElementSize(1), Src, MaxC);
8416 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8418 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8428 MI.eraseFromParent();
8433 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8435 DstTy.changeElementSize(1), Src, Src);
8438 MI.eraseFromParent();
8445 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8454 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8465 MI.eraseFromParent();
8471 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8473 DstTy.changeElementSize(1), Src, Src);
8475 MI.eraseFromParent();
8485 auto [Dst, Src] =
MI.getFirst2Regs();
8487 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8489 if (MRI.getType(Src).isVector())
8493 unsigned Flags =
MI.getFlags();
8496 MI.eraseFromParent();
8500 const unsigned ExpMask = 0x7ff;
8501 const unsigned ExpBiasf64 = 1023;
8502 const unsigned ExpBiasf16 = 15;
8531 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8591 MI.eraseFromParent();
8597 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8601 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8608 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8609 LLT Ty = MRI.getType(Dst);
8611 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8612 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8613 MI.eraseFromParent();
8619 case TargetOpcode::G_SMIN:
8621 case TargetOpcode::G_SMAX:
8623 case TargetOpcode::G_UMIN:
8625 case TargetOpcode::G_UMAX:
8633 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8638 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8639 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8641 MI.eraseFromParent();
8650 LLT DstTy = MRI.getType(Dst);
8651 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8661 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8662 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8664 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8667 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8668 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8669 if (TLI.preferSelectsOverBooleanArithmetic(
8672 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8673 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8675 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8676 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8682 unsigned BoolExtOp =
8684 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8685 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8689 MI.eraseFromParent();
8695 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8696 const int Src0Size = Src0Ty.getScalarSizeInBits();
8697 const int Src1Size = Src1Ty.getScalarSizeInBits();
8702 auto NotSignBitMask =
MIRBuilder.buildConstant(
8707 if (Src0Ty == Src1Ty) {
8708 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8709 }
else if (Src0Size > Src1Size) {
8710 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8711 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8712 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8713 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8715 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8716 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8717 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8718 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8724 unsigned Flags =
MI.getFlags();
8731 MI.eraseFromParent();
8742 switch (
MI.getOpcode()) {
8743 case TargetOpcode::G_FMINNUM:
8744 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8746 case TargetOpcode::G_FMINIMUMNUM:
8747 NewOp = TargetOpcode::G_FMINNUM;
8749 case TargetOpcode::G_FMAXNUM:
8750 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8752 case TargetOpcode::G_FMAXIMUMNUM:
8753 NewOp = TargetOpcode::G_FMAXNUM;
8759 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8760 LLT Ty = MRI.getType(Dst);
8770 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8773 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8778 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8779 MI.eraseFromParent();
8785 unsigned Opc =
MI.getOpcode();
8786 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8787 LLT Ty = MRI.getType(Dst);
8790 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
8792 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
8793 unsigned OpcNonIeee =
8794 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
8795 bool MinMaxMustRespectOrderedZero =
false;
8799 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
8801 MinMaxMustRespectOrderedZero =
true;
8802 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
8807 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
8815 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
8819 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
8821 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
8831 const unsigned Flags =
MI.getFlags();
8837 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
8839 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
8841 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
8843 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
8845 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
8850 MI.eraseFromParent();
8857 LLT Ty = MRI.getType(DstReg);
8858 unsigned Flags =
MI.getFlags();
8863 MI.eraseFromParent();
8869 auto [DstReg,
X] =
MI.getFirst2Regs();
8870 const unsigned Flags =
MI.getFlags();
8871 const LLT Ty = MRI.getType(DstReg);
8883 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8885 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8890 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8891 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8892 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8893 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8895 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8897 MI.eraseFromParent();
8902 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8903 unsigned Flags =
MI.getFlags();
8904 LLT Ty = MRI.getType(DstReg);
8911 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8912 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8915 SrcReg, Zero, Flags);
8917 SrcReg, Trunc, Flags);
8921 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8922 MI.eraseFromParent();
8928 const unsigned NumOps =
MI.getNumOperands();
8929 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8930 unsigned PartSize = Src0Ty.getSizeInBits();
8935 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8936 const unsigned Offset = (
I - 1) * PartSize;
8939 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8942 MRI.createGenericVirtualRegister(WideTy);
8945 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8946 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8947 ResultReg = NextResult;
8950 if (DstTy.isPointer()) {
8951 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8952 DstTy.getAddressSpace())) {
8960 MI.eraseFromParent();
8966 const unsigned NumDst =
MI.getNumOperands() - 1;
8967 Register SrcReg =
MI.getOperand(NumDst).getReg();
8968 Register Dst0Reg =
MI.getOperand(0).getReg();
8969 LLT DstTy = MRI.getType(Dst0Reg);
8978 LLT IntTy = MRI.getType(SrcReg);
8983 unsigned Offset = DstSize;
8984 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
8986 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
8990 MI.eraseFromParent();
9009 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9010 InsertVal =
MI.getOperand(2).getReg();
9012 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9014 LLT VecTy = MRI.getType(SrcVec);
9024 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9025 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9027 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9030 MI.eraseFromParent();
9035 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9046 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9053 int64_t
Offset = IdxVal * EltBytes;
9064 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9067 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9069 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9072 MI.eraseFromParent();
9078 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9079 MI.getFirst3RegLLTs();
9087 for (
int Idx : Mask) {
9089 if (!Undef.isValid())
9090 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
9095 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9097 int NumElts = Src0Ty.getNumElements();
9098 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9099 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9100 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9101 auto Extract =
MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK);
9105 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9106 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9107 MI.eraseFromParent();
9113 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9114 MI.getFirst4RegLLTs();
9116 if (VecTy.isScalableVector())
9132 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9135 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9138 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9141 std::optional<APInt> PassthruSplatVal =
9144 if (PassthruSplatVal.has_value()) {
9146 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9147 }
else if (HasPassthru) {
9148 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9149 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9155 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9159 unsigned NumElmts = VecTy.getNumElements();
9160 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9162 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9165 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9168 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9173 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9175 if (HasPassthru &&
I == NumElmts - 1) {
9178 auto AllLanesSelected =
MIRBuilder.buildICmp(
9180 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9181 {OutPos, EndOfVector});
9185 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9187 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9192 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9194 MI.eraseFromParent();
9205 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9211 if (Alignment >
Align(1)) {
9214 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9223 const auto &MF = *
MI.getMF();
9229 Register AllocSize =
MI.getOperand(1).getReg();
9232 LLT PtrTy = MRI.getType(Dst);
9233 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9240 MI.eraseFromParent();
9246 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9251 MI.eraseFromParent();
9257 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9262 MI.eraseFromParent();
9268 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9269 unsigned Offset =
MI.getOperand(2).getImm();
9272 if (SrcTy.isVector()) {
9273 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9274 unsigned DstSize = DstTy.getSizeInBits();
9276 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9277 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9279 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9283 for (
unsigned Idx =
Offset / SrcEltSize;
9284 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9285 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9287 if (SubVectorElts.
size() == 1)
9288 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9290 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9292 MI.eraseFromParent();
9297 if (DstTy.isScalar() &&
9298 (SrcTy.isScalar() ||
9299 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9300 LLT SrcIntTy = SrcTy;
9301 if (!SrcTy.isScalar()) {
9303 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9310 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9314 MI.eraseFromParent();
9322 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9325 LLT DstTy = MRI.getType(Src);
9326 LLT InsertTy = MRI.getType(InsertSrc);
9334 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9336 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9340 for (; Idx <
Offset / EltSize; ++Idx) {
9341 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9346 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9347 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9349 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9358 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9361 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9362 MI.eraseFromParent();
9376 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9380 LLT IntDstTy = DstTy;
9384 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9389 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9395 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9401 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9402 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9403 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9406 MI.eraseFromParent();
9412 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9413 MI.getFirst4RegLLTs();
9414 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9417 LLT BoolTy = Dst1Ty;
9419 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9436 auto ResultLowerThanLHS =
9441 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9444 MI.eraseFromParent();
9450 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9451 const LLT Ty = MRI.getType(Res);
9454 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9455 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9456 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9467 MI.eraseFromParent();
9472 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9473 const LLT Ty = MRI.getType(Res);
9476 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9477 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9478 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9483 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9488 MI.eraseFromParent();
9494 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9495 LLT Ty = MRI.getType(Res);
9499 switch (
MI.getOpcode()) {
9502 case TargetOpcode::G_UADDSAT:
9505 BaseOp = TargetOpcode::G_ADD;
9507 case TargetOpcode::G_SADDSAT:
9510 BaseOp = TargetOpcode::G_ADD;
9512 case TargetOpcode::G_USUBSAT:
9515 BaseOp = TargetOpcode::G_SUB;
9517 case TargetOpcode::G_SSUBSAT:
9520 BaseOp = TargetOpcode::G_SUB;
9535 uint64_t NumBits = Ty.getScalarSizeInBits();
9546 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9554 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9559 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9560 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9563 MI.eraseFromParent();
9569 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9570 LLT Ty = MRI.getType(Res);
9574 unsigned OverflowOp;
9575 switch (
MI.getOpcode()) {
9578 case TargetOpcode::G_UADDSAT:
9581 OverflowOp = TargetOpcode::G_UADDO;
9583 case TargetOpcode::G_SADDSAT:
9586 OverflowOp = TargetOpcode::G_SADDO;
9588 case TargetOpcode::G_USUBSAT:
9591 OverflowOp = TargetOpcode::G_USUBO;
9593 case TargetOpcode::G_SSUBSAT:
9596 OverflowOp = TargetOpcode::G_SSUBO;
9601 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9602 Register Tmp = OverflowRes.getReg(0);
9603 Register Ov = OverflowRes.getReg(1);
9612 uint64_t NumBits = Ty.getScalarSizeInBits();
9613 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9614 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9617 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9625 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9629 MI.eraseFromParent();
9635 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9636 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9637 "Expected shlsat opcode!");
9638 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9639 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9640 LLT Ty = MRI.getType(Res);
9644 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9645 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9654 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9659 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9661 MI.eraseFromParent();
9666 auto [Dst, Src] =
MI.getFirst2Regs();
9667 const LLT Ty = MRI.getType(Src);
9668 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9669 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9672 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9673 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9674 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9675 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9678 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9680 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9681 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9682 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9684 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9685 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9686 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9688 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9689 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9690 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9692 Res.getInstr()->getOperand(0).setReg(Dst);
9694 MI.eraseFromParent();
9701 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9704 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9705 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9706 return B.buildOr(Dst,
LHS,
RHS);
9711 auto [Dst, Src] =
MI.getFirst2Regs();
9712 const LLT SrcTy = MRI.getType(Src);
9713 unsigned Size = SrcTy.getScalarSizeInBits();
9714 unsigned VSize = SrcTy.getSizeInBits();
9717 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9718 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9719 {LLT::fixed_vector(VSize / 8, 8),
9720 LLT::fixed_vector(VSize / 8, 8)}}))) {
9725 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9726 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9727 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9731 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9754 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9758 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9761 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9765 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9769 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9774 MI.eraseFromParent();
9782 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9783 int NameOpIdx = IsRead ? 1 : 0;
9784 int ValRegIndex = IsRead ? 0 : 1;
9786 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9787 const LLT Ty = MRI.getType(ValReg);
9789 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9796 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9797 Fn,
MI.getDebugLoc()));
9801 MI.eraseFromParent();
9810 MI.eraseFromParent();
9816 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9817 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9819 LLT OrigTy = MRI.getType(Result);
9823 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9824 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9826 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9828 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9829 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9832 MI.eraseFromParent();
9838 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9843 MI.eraseFromParent();
9848 MI.eraseFromParent();
9855 unsigned BitSize = SrcTy.getScalarSizeInBits();
9859 if (SrcTy.isVector())
9860 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9861 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9867 APInt ExpMask = Inf;
9873 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9874 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9875 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9876 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9877 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9879 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9883 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9885 LLT DstTyCopy = DstTy;
9887 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9915 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9918 Mask &= ~PartialCheck;
9927 else if (PartialCheck ==
fcZero)
9939 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9940 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9943 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9945 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9946 appendToRes(SubnormalRes);
9953 else if (PartialCheck ==
fcInf)
9958 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9965 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
9966 if (PartialCheck ==
fcNan) {
9970 }
else if (PartialCheck ==
fcQNan) {
9980 Abs, InfWithQnanBitC);
9981 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
9988 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
9990 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
9991 APInt MaxExpMinusOne = ExpMask - ExpLSB;
9994 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
9996 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
9999 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10000 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10002 appendToRes(NormalRes);
10006 MI.eraseFromParent();
10012 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10013 MI.getFirst4RegLLTs();
10015 bool IsEltPtr = DstTy.isPointerOrPointerVector();
10019 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10020 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10024 if (MaskTy.isScalar()) {
10032 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10036 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
10038 if (DstTy.isVector()) {
10040 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
10041 MaskReg = ShufSplat.getReg(0);
10046 }
else if (!DstTy.isVector()) {
10051 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10055 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10056 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10057 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10064 MI.eraseFromParent();
10070 unsigned Opcode =
MI.getOpcode();
10073 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10074 : TargetOpcode::G_UDIV,
10075 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10077 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10078 : TargetOpcode::G_UREM,
10079 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10080 MI.eraseFromParent();
10090 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10094 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10097 MI.eraseFromParent();
10107 Register SrcReg =
MI.getOperand(1).getReg();
10108 LLT Ty = MRI.getType(SrcReg);
10109 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10112 MI.eraseFromParent();
10118 Register SrcReg =
MI.getOperand(1).getReg();
10119 Register DestReg =
MI.getOperand(0).getReg();
10121 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10122 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10125 MI.eraseFromParent();
10131 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10132 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10133 "Expected G_ABDS or G_ABDU instruction");
10135 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10136 LLT Ty = MRI.getType(LHS);
10146 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10148 MI.eraseFromParent();
10154 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10155 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10156 "Expected G_ABDS or G_ABDU instruction");
10158 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10159 LLT Ty = MRI.getType(LHS);
10164 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10165 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10166 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10168 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10169 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10171 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10173 MI.eraseFromParent();
10178 Register SrcReg =
MI.getOperand(1).getReg();
10179 Register DstReg =
MI.getOperand(0).getReg();
10181 LLT Ty = MRI.getType(DstReg);
10189 MI.eraseFromParent();
10195 Register SrcReg =
MI.getOperand(1).getReg();
10196 LLT SrcTy = MRI.getType(SrcReg);
10197 LLT DstTy = MRI.getType(SrcReg);
10200 if (SrcTy.isScalar()) {
10205 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10216 Register ListPtr =
MI.getOperand(1).getReg();
10217 LLT PtrTy = MRI.getType(ListPtr);
10224 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10226 const Align A(
MI.getOperand(2).getImm());
10228 if (
A > TLI.getMinStackArgumentAlignment()) {
10230 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10231 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10232 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10233 VAList = AndDst.getReg(0);
10240 LLT LLTTy = MRI.getType(Dst);
10243 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10244 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10249 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10251 Align EltAlignment =
DL.getABITypeAlign(Ty);
10254 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10256 MI.eraseFromParent();
10271 unsigned Limit,
const MemOp &
Op,
10272 unsigned DstAS,
unsigned SrcAS,
10273 const AttributeList &FuncAttributes,
10275 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10285 if (
Op.isFixedDstAlign())
10286 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10289 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10293 unsigned NumMemOps = 0;
10296 unsigned TySize = Ty.getSizeInBytes();
10297 while (TySize >
Size) {
10306 assert(NewTySize > 0 &&
"Could not find appropriate type");
10313 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10315 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10321 TySize = NewTySize;
10325 if (++NumMemOps > Limit)
10328 MemOps.push_back(Ty);
10338 unsigned NumBits = Ty.getScalarSizeInBits();
10340 if (!Ty.isVector() && ValVRegAndVal) {
10341 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10349 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10370 uint64_t KnownLen,
Align Alignment,
10372 auto &MF = *
MI.getParent()->getParent();
10377 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10379 bool DstAlignCanChange =
false;
10383 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10385 DstAlignCanChange =
true;
10387 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10388 std::vector<LLT> MemOps;
10390 const auto &DstMMO = **
MI.memoperands_begin();
10391 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10394 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10405 if (DstAlignCanChange) {
10408 Align NewAlign =
DL.getABITypeAlign(IRTy);
10409 if (NewAlign > Alignment) {
10410 Alignment = NewAlign;
10418 MachineIRBuilder MIB(
MI);
10420 LLT LargestTy = MemOps[0];
10421 for (
unsigned i = 1; i < MemOps.size(); i++)
10423 LargestTy = MemOps[i];
10435 LLT PtrTy = MRI.getType(Dst);
10436 unsigned DstOff = 0;
10437 unsigned Size = KnownLen;
10438 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10439 LLT Ty = MemOps[
I];
10441 if (TySize >
Size) {
10444 assert(
I == MemOps.size() - 1 &&
I != 0);
10445 DstOff -= TySize -
Size;
10455 TLI.isTruncateFree(LargestVT, VT))
10456 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10469 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10472 MIB.buildStore(
Value,
Ptr, *StoreMMO);
10477 MI.eraseFromParent();
10483 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10485 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10487 const auto *MMOIt =
MI.memoperands_begin();
10489 bool IsVolatile =
MemOp->isVolatile();
10495 "inline memcpy with dynamic size is not yet supported");
10496 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10497 if (KnownLen == 0) {
10498 MI.eraseFromParent();
10502 const auto &DstMMO = **
MI.memoperands_begin();
10503 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10504 Align DstAlign = DstMMO.getBaseAlign();
10505 Align SrcAlign = SrcMMO.getBaseAlign();
10507 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10514 Align SrcAlign,
bool IsVolatile) {
10515 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10516 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10517 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10524 Align SrcAlign,
bool IsVolatile) {
10525 auto &MF = *
MI.getParent()->getParent();
10530 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10532 bool DstAlignCanChange =
false;
10534 Align Alignment = std::min(DstAlign, SrcAlign);
10538 DstAlignCanChange =
true;
10544 std::vector<LLT> MemOps;
10546 const auto &DstMMO = **
MI.memoperands_begin();
10547 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10553 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10559 if (DstAlignCanChange) {
10562 Align NewAlign =
DL.getABITypeAlign(IRTy);
10567 if (!
TRI->hasStackRealignment(MF))
10569 NewAlign = std::min(NewAlign, *StackAlign);
10571 if (NewAlign > Alignment) {
10572 Alignment = NewAlign;
10580 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10582 MachineIRBuilder MIB(
MI);
10588 unsigned CurrOffset = 0;
10589 unsigned Size = KnownLen;
10590 for (
auto CopyTy : MemOps) {
10593 if (CopyTy.getSizeInBytes() >
Size)
10594 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10605 if (CurrOffset != 0) {
10606 LLT SrcTy = MRI.getType(Src);
10609 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10611 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10615 if (CurrOffset != 0) {
10616 LLT DstTy = MRI.getType(Dst);
10617 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10619 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10620 CurrOffset += CopyTy.getSizeInBytes();
10621 Size -= CopyTy.getSizeInBytes();
10624 MI.eraseFromParent();
10630 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10632 auto &MF = *
MI.getParent()->getParent();
10637 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10639 bool DstAlignCanChange =
false;
10642 Align Alignment = std::min(DstAlign, SrcAlign);
10644 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10646 DstAlignCanChange =
true;
10648 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10649 std::vector<LLT> MemOps;
10651 const auto &DstMMO = **
MI.memoperands_begin();
10652 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10653 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10654 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10661 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10667 if (DstAlignCanChange) {
10670 Align NewAlign =
DL.getABITypeAlign(IRTy);
10675 if (!
TRI->hasStackRealignment(MF))
10676 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10677 NewAlign = std::min(NewAlign, *StackAlign);
10679 if (NewAlign > Alignment) {
10680 Alignment = NewAlign;
10688 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10690 MachineIRBuilder MIB(
MI);
10694 unsigned CurrOffset = 0;
10695 SmallVector<Register, 16> LoadVals;
10696 for (
auto CopyTy : MemOps) {
10703 if (CurrOffset != 0) {
10704 LLT SrcTy = MRI.getType(Src);
10707 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10709 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10710 CurrOffset += CopyTy.getSizeInBytes();
10714 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10715 LLT CopyTy = MemOps[
I];
10721 if (CurrOffset != 0) {
10722 LLT DstTy = MRI.getType(Dst);
10725 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10727 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10730 MI.eraseFromParent();
10736 const unsigned Opc =
MI.getOpcode();
10739 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10740 Opc == TargetOpcode::G_MEMSET) &&
10741 "Expected memcpy like instruction");
10743 auto MMOIt =
MI.memoperands_begin();
10748 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10750 if (
Opc != TargetOpcode::G_MEMSET) {
10751 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10752 MemOp = *(++MMOIt);
10753 SrcAlign =
MemOp->getBaseAlign();
10758 if (!LenVRegAndVal)
10760 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10762 if (KnownLen == 0) {
10763 MI.eraseFromParent();
10767 if (MaxLen && KnownLen > MaxLen)
10770 bool IsVolatile =
MemOp->isVolatile();
10771 if (
Opc == TargetOpcode::G_MEMCPY) {
10772 auto &MF = *
MI.getParent()->getParent();
10775 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10776 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10779 if (
Opc == TargetOpcode::G_MEMMOVE)
10780 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10781 if (
Opc == TargetOpcode::G_MEMSET)
10782 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 unsigned 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 rmNearestTiesToEven
static const fltSemantics & IEEEdouble()
static constexpr roundingMode rmTowardZero
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.
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)