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);
3300 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3316 LLT VecTy = MRI.getType(VecReg);
3336 case TargetOpcode::G_FADD:
3337 case TargetOpcode::G_FMUL:
3338 case TargetOpcode::G_FSUB:
3339 case TargetOpcode::G_FMA:
3340 case TargetOpcode::G_FMAD:
3341 case TargetOpcode::G_FNEG:
3342 case TargetOpcode::G_FABS:
3343 case TargetOpcode::G_FCANONICALIZE:
3344 case TargetOpcode::G_FMINNUM:
3345 case TargetOpcode::G_FMAXNUM:
3346 case TargetOpcode::G_FMINNUM_IEEE:
3347 case TargetOpcode::G_FMAXNUM_IEEE:
3348 case TargetOpcode::G_FMINIMUM:
3349 case TargetOpcode::G_FMAXIMUM:
3350 case TargetOpcode::G_FMINIMUMNUM:
3351 case TargetOpcode::G_FMAXIMUMNUM:
3352 case TargetOpcode::G_FDIV:
3353 case TargetOpcode::G_FREM:
3354 case TargetOpcode::G_FCEIL:
3355 case TargetOpcode::G_FFLOOR:
3356 case TargetOpcode::G_FCOS:
3357 case TargetOpcode::G_FSIN:
3358 case TargetOpcode::G_FTAN:
3359 case TargetOpcode::G_FACOS:
3360 case TargetOpcode::G_FASIN:
3361 case TargetOpcode::G_FATAN:
3362 case TargetOpcode::G_FATAN2:
3363 case TargetOpcode::G_FCOSH:
3364 case TargetOpcode::G_FSINH:
3365 case TargetOpcode::G_FTANH:
3366 case TargetOpcode::G_FLOG10:
3367 case TargetOpcode::G_FLOG:
3368 case TargetOpcode::G_FLOG2:
3369 case TargetOpcode::G_FRINT:
3370 case TargetOpcode::G_FNEARBYINT:
3371 case TargetOpcode::G_FSQRT:
3372 case TargetOpcode::G_FEXP:
3373 case TargetOpcode::G_FEXP2:
3374 case TargetOpcode::G_FEXP10:
3375 case TargetOpcode::G_FPOW:
3376 case TargetOpcode::G_INTRINSIC_TRUNC:
3377 case TargetOpcode::G_INTRINSIC_ROUND:
3378 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3382 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3388 case TargetOpcode::G_FMODF: {
3398 case TargetOpcode::G_FPOWI:
3399 case TargetOpcode::G_FLDEXP:
3400 case TargetOpcode::G_STRICT_FLDEXP: {
3402 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3423 case TargetOpcode::G_FFREXP: {
3436 case TargetOpcode::G_INTTOPTR:
3444 case TargetOpcode::G_PTRTOINT:
3452 case TargetOpcode::G_BUILD_VECTOR: {
3456 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3462 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3470 case TargetOpcode::G_SEXT_INREG:
3479 case TargetOpcode::G_PTRMASK: {
3487 case TargetOpcode::G_VECREDUCE_ADD: {
3496 case TargetOpcode::G_VECREDUCE_FADD:
3497 case TargetOpcode::G_VECREDUCE_FMUL:
3498 case TargetOpcode::G_VECREDUCE_FMIN:
3499 case TargetOpcode::G_VECREDUCE_FMAX:
3500 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3501 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3506 LLT VecTy = MRI.getType(VecReg);
3515 case TargetOpcode::G_VSCALE: {
3522 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3527 case TargetOpcode::G_SPLAT_VECTOR: {
3536 case TargetOpcode::G_INSERT_SUBVECTOR: {
3544 LLT SubVecTy = MRI.getType(SubVec);
3548 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3549 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3550 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3554 auto SplatZero =
MIRBuilder.buildSplatVector(
3559 MI.eraseFromParent();
3568 auto Unmerge =
B.buildUnmerge(Ty, Src);
3569 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3578 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3580 LLT DstLLT =
MRI.getType(DstReg);
3592 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3601 MI.eraseFromParent();
3612 MI.eraseFromParent();
3619 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3620 if (SrcTy.isVector()) {
3624 if (DstTy.isVector()) {
3625 int NumDstElt = DstTy.getNumElements();
3626 int NumSrcElt = SrcTy.getNumElements();
3629 LLT DstCastTy = DstEltTy;
3630 LLT SrcPartTy = SrcEltTy;
3634 if (NumSrcElt < NumDstElt) {
3644 SrcPartTy = SrcEltTy;
3645 }
else if (NumSrcElt > NumDstElt) {
3656 DstCastTy = DstEltTy;
3661 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3665 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3666 MI.eraseFromParent();
3670 if (DstTy.isVector()) {
3673 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3674 MI.eraseFromParent();
3690 unsigned NewEltSize,
3691 unsigned OldEltSize) {
3692 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3693 LLT IdxTy =
B.getMRI()->getType(Idx);
3696 auto OffsetMask =
B.buildConstant(
3698 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3699 return B.buildShl(IdxTy, OffsetIdx,
3700 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3715 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3719 unsigned OldNumElts = SrcVecTy.getNumElements();
3726 if (NewNumElts > OldNumElts) {
3737 if (NewNumElts % OldNumElts != 0)
3741 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3745 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3748 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3750 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3751 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3752 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3753 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3754 NewOps[
I] = Elt.getReg(0);
3757 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3759 MI.eraseFromParent();
3763 if (NewNumElts < OldNumElts) {
3764 if (NewEltSize % OldEltSize != 0)
3786 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3787 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3790 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3794 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3795 ScaledIdx).getReg(0);
3803 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3805 MI.eraseFromParent();
3819 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3820 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3821 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3822 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3825 auto EltMask =
B.buildConstant(
3829 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3830 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3833 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3837 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3851 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3852 MI.getFirst4RegLLTs();
3864 if (NewNumElts < OldNumElts) {
3865 if (NewEltSize % OldEltSize != 0)
3874 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3875 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3878 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3882 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3883 ScaledIdx).getReg(0);
3893 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3894 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3898 MI.eraseFromParent();
3928 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3932 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3933 return UnableToLegalize;
3938 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3940 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3949 MI.eraseFromParent();
3967 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3968 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3978 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3979 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3981 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
3982 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
3984 MI.eraseFromParent();
4014 LLT DstTy = MRI.getType(Dst);
4015 LLT SrcTy = MRI.getType(Src);
4021 if (DstTy == CastTy)
4029 if (CastEltSize < DstEltSize)
4032 auto AdjustAmt = CastEltSize / DstEltSize;
4033 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4034 SrcTyMinElts % AdjustAmt != 0)
4039 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4040 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4043 ES->eraseFromParent();
4078 LLT DstTy = MRI.getType(Dst);
4079 LLT BigVecTy = MRI.getType(BigVec);
4080 LLT SubVecTy = MRI.getType(SubVec);
4082 if (DstTy == CastTy)
4097 if (CastEltSize < DstEltSize)
4100 auto AdjustAmt = CastEltSize / DstEltSize;
4101 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4102 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4108 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4109 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4111 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4114 ES->eraseFromParent();
4122 LLT DstTy = MRI.getType(DstReg);
4130 if (MemSizeInBits != MemStoreSizeInBits) {
4147 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4151 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4152 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4154 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4157 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4159 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4162 if (DstTy != LoadTy)
4170 if (
MIRBuilder.getDataLayout().isBigEndian())
4188 uint64_t LargeSplitSize, SmallSplitSize;
4193 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4200 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4203 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4214 if (Alignment.
value() * 8 > MemSizeInBits &&
4219 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4236 LLT PtrTy = MRI.getType(PtrReg);
4239 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4243 LargeSplitSize / 8);
4244 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4245 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4247 SmallPtr, *SmallMMO);
4249 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4250 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4252 if (AnyExtTy == DstTy)
4253 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4255 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4259 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4279 LLT SrcTy = MRI.getType(SrcReg);
4287 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4293 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4295 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4299 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4303 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4318 uint64_t LargeSplitSize, SmallSplitSize;
4325 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4328 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4337 if (SrcTy.isPointer()) {
4339 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4342 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4345 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4346 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4349 LLT PtrTy = MRI.getType(PtrReg);
4352 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4358 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4359 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4368 LLT SrcTy = MRI.getType(SrcReg);
4374 assert(SrcTy.isVector() &&
"Expect a vector store type");
4381 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4385 auto Elt =
MIRBuilder.buildExtractVectorElement(
4386 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4387 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4388 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4394 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4395 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4399 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4410 switch (
MI.getOpcode()) {
4411 case TargetOpcode::G_LOAD: {
4429 case TargetOpcode::G_STORE: {
4445 case TargetOpcode::G_SELECT: {
4449 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4451 dbgs() <<
"bitcast action not implemented for vector select\n");
4462 case TargetOpcode::G_AND:
4463 case TargetOpcode::G_OR:
4464 case TargetOpcode::G_XOR: {
4472 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4474 case TargetOpcode::G_INSERT_VECTOR_ELT:
4476 case TargetOpcode::G_CONCAT_VECTORS:
4478 case TargetOpcode::G_SHUFFLE_VECTOR:
4480 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4482 case TargetOpcode::G_INSERT_SUBVECTOR:
4490void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4500 switch(
MI.getOpcode()) {
4503 case TargetOpcode::G_FCONSTANT:
4505 case TargetOpcode::G_BITCAST:
4507 case TargetOpcode::G_SREM:
4508 case TargetOpcode::G_UREM: {
4509 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4511 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4512 {MI.getOperand(1), MI.getOperand(2)});
4514 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4516 MI.eraseFromParent();
4519 case TargetOpcode::G_SADDO:
4520 case TargetOpcode::G_SSUBO:
4522 case TargetOpcode::G_SADDE:
4524 case TargetOpcode::G_SSUBE:
4526 case TargetOpcode::G_UMULH:
4527 case TargetOpcode::G_SMULH:
4529 case TargetOpcode::G_SMULO:
4530 case TargetOpcode::G_UMULO: {
4533 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4534 LLT Ty = MRI.getType(Res);
4536 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4537 ? TargetOpcode::G_SMULH
4538 : TargetOpcode::G_UMULH;
4542 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4543 MI.removeOperand(1);
4546 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4554 if (Opcode == TargetOpcode::G_SMULH) {
4555 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4556 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4563 case TargetOpcode::G_FNEG: {
4564 auto [Res, SubByReg] =
MI.getFirst2Regs();
4565 LLT Ty = MRI.getType(Res);
4569 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4570 MI.eraseFromParent();
4573 case TargetOpcode::G_FSUB:
4574 case TargetOpcode::G_STRICT_FSUB: {
4575 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4576 LLT Ty = MRI.getType(Res);
4581 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4582 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4586 MI.eraseFromParent();
4589 case TargetOpcode::G_FMAD:
4591 case TargetOpcode::G_FFLOOR:
4593 case TargetOpcode::G_LROUND:
4594 case TargetOpcode::G_LLROUND: {
4597 LLT SrcTy = MRI.getType(SrcReg);
4598 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4601 MI.eraseFromParent();
4604 case TargetOpcode::G_INTRINSIC_ROUND:
4606 case TargetOpcode::G_FRINT: {
4609 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4612 case TargetOpcode::G_INTRINSIC_LRINT:
4613 case TargetOpcode::G_INTRINSIC_LLRINT: {
4616 LLT SrcTy = MRI.getType(SrcReg);
4618 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4620 MI.eraseFromParent();
4623 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4624 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4625 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4626 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4627 **
MI.memoperands_begin());
4629 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4630 MI.eraseFromParent();
4633 case TargetOpcode::G_LOAD:
4634 case TargetOpcode::G_SEXTLOAD:
4635 case TargetOpcode::G_ZEXTLOAD:
4637 case TargetOpcode::G_STORE:
4639 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4640 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4641 case TargetOpcode::G_CTLZ:
4642 case TargetOpcode::G_CTTZ:
4643 case TargetOpcode::G_CTPOP:
4646 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4648 Register NewRes = MRI.cloneVirtualRegister(Res);
4655 MI.eraseFromParent();
4659 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4660 const LLT CondTy = MRI.getType(CarryOut);
4661 const LLT Ty = MRI.getType(Res);
4663 Register NewRes = MRI.cloneVirtualRegister(Res);
4666 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4672 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4673 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4680 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4685 MI.eraseFromParent();
4689 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4694 MI.eraseFromParent();
4698 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4699 const LLT CondTy = MRI.getType(BorrowOut);
4700 const LLT Ty = MRI.getType(Res);
4703 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4709 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4710 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4717 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4718 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4720 MI.eraseFromParent();
4753 case G_MERGE_VALUES:
4755 case G_UNMERGE_VALUES:
4757 case TargetOpcode::G_SEXT_INREG: {
4758 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4759 int64_t SizeInBits =
MI.getOperand(2).getImm();
4761 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4762 LLT DstTy = MRI.getType(DstReg);
4763 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4766 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4767 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4768 MI.eraseFromParent();
4771 case G_EXTRACT_VECTOR_ELT:
4772 case G_INSERT_VECTOR_ELT:
4774 case G_SHUFFLE_VECTOR:
4776 case G_VECTOR_COMPRESS:
4778 case G_DYN_STACKALLOC:
4782 case G_STACKRESTORE:
4792 case G_READ_REGISTER:
4793 case G_WRITE_REGISTER:
4800 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4801 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4807 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4812 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4823 bool IsSigned =
MI.getOpcode() == G_ABDS;
4824 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4825 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4826 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4850 case G_MEMCPY_INLINE:
4851 return lowerMemcpyInline(
MI);
4862 case G_ATOMICRMW_SUB: {
4863 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4864 const LLT ValTy = MRI.getType(Val);
4868 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4869 MI.eraseFromParent();
4892 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4896 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4902 Align StackTypeAlign =
4909 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4910 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4915 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4927 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4930 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4941 "Converting bits to bytes lost precision");
4947 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4948 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4950 if (IdxTy != MRI.getType(Index))
4951 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4956 LLT PtrTy = MRI.getType(VecPtr);
4957 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4965 std::initializer_list<unsigned> NonVecOpIndices) {
4966 if (
MI.getNumMemOperands() != 0)
4969 LLT VecTy =
MRI.getType(
MI.getReg(0));
4983 if (!Ty.isVector()) {
4989 if (Ty.getNumElements() != NumElts)
5004 assert(Ty.isVector() &&
"Expected vector type");
5007 int NumParts, NumLeftover;
5008 std::tie(NumParts, NumLeftover) =
5011 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5012 for (
int i = 0; i < NumParts; ++i) {
5017 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5026 for (
unsigned i = 0; i <
N; ++i) {
5028 Ops.push_back(
Op.getReg());
5029 else if (
Op.isImm())
5030 Ops.push_back(
Op.getImm());
5031 else if (
Op.isPredicate())
5053 std::initializer_list<unsigned> NonVecOpIndices) {
5055 "Non-compatible opcode or not specified non-vector operands");
5056 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5058 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5059 unsigned NumDefs =
MI.getNumDefs();
5067 for (
unsigned i = 0; i < NumDefs; ++i) {
5068 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5076 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5077 ++UseIdx, ++UseNo) {
5080 MI.getOperand(UseIdx));
5089 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5093 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5095 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5096 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5099 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5100 Uses.push_back(InputOpsPieces[InputNo][i]);
5103 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5104 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5109 for (
unsigned i = 0; i < NumDefs; ++i)
5110 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5112 for (
unsigned i = 0; i < NumDefs; ++i)
5113 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5116 MI.eraseFromParent();
5123 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5125 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5126 unsigned NumDefs =
MI.getNumDefs();
5130 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5135 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5136 UseIdx += 2, ++UseNo) {
5144 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5146 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5147 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5149 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5152 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5153 Phi.addUse(InputOpsPieces[j][i]);
5154 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5164 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5166 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5169 MI.eraseFromParent();
5177 const int NumDst =
MI.getNumOperands() - 1;
5178 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5179 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5180 LLT SrcTy = MRI.getType(SrcReg);
5182 if (TypeIdx != 1 || NarrowTy == DstTy)
5189 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5192 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5206 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5207 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5208 const int PartsPerUnmerge = NumDst / NumUnmerge;
5210 for (
int I = 0;
I != NumUnmerge; ++
I) {
5211 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5213 for (
int J = 0; J != PartsPerUnmerge; ++J)
5214 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5215 MIB.addUse(Unmerge.getReg(
I));
5218 MI.eraseFromParent();
5225 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5229 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5231 if (NarrowTy == SrcTy)
5239 assert(SrcTy.isVector() &&
"Expected vector types");
5241 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5255 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5256 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5257 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5263 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5264 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5265 ++i,
Offset += NumNarrowTyElts) {
5268 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5271 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5272 MI.eraseFromParent();
5276 assert(TypeIdx == 0 &&
"Bad type index");
5277 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5292 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5293 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5295 for (
unsigned i = 0; i < NumParts; ++i) {
5297 for (
unsigned j = 0; j < NumElts; ++j)
5298 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5300 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5303 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5304 MI.eraseFromParent();
5312 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5314 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5316 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5318 InsertVal =
MI.getOperand(2).getReg();
5320 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5321 LLT VecTy = MRI.getType(SrcVec);
5327 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5331 MI.eraseFromParent();
5340 SplitPieces[IdxVal] = InsertVal;
5341 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5343 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5347 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5350 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5351 TargetOpcode::G_ANYEXT);
5355 LLT IdxTy = MRI.getType(Idx);
5356 int64_t PartIdx = IdxVal / NewNumElts;
5358 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5361 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5364 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5365 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5366 VecParts[PartIdx] = InsertPart.getReg(0);
5370 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5372 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5376 MI.eraseFromParent();
5396 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5408 LLT ValTy = MRI.getType(ValReg);
5417 int NumLeftover = -1;
5423 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5425 NumParts = NarrowRegs.
size();
5426 NumLeftover = NarrowLeftoverRegs.
size();
5433 LLT PtrTy = MRI.getType(AddrReg);
5436 unsigned TotalSize = ValTy.getSizeInBits();
5443 auto MMO = LdStMI.
getMMO();
5445 unsigned NumParts,
unsigned Offset) ->
unsigned {
5448 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5450 unsigned ByteOffset =
Offset / 8;
5453 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5460 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5461 ValRegs.push_back(Dst);
5462 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5464 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5473 unsigned HandledOffset =
5474 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5478 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5481 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5482 LeftoverTy, NarrowLeftoverRegs);
5496 switch (
MI.getOpcode()) {
5497 case G_IMPLICIT_DEF:
5513 case G_FCANONICALIZE:
5530 case G_INTRINSIC_LRINT:
5531 case G_INTRINSIC_LLRINT:
5532 case G_INTRINSIC_ROUND:
5533 case G_INTRINSIC_ROUNDEVEN:
5536 case G_INTRINSIC_TRUNC:
5564 case G_FMINNUM_IEEE:
5565 case G_FMAXNUM_IEEE:
5587 case G_CTLZ_ZERO_UNDEF:
5589 case G_CTTZ_ZERO_UNDEF:
5605 case G_ADDRSPACE_CAST:
5618 case G_STRICT_FLDEXP:
5627 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5632 case G_UNMERGE_VALUES:
5634 case G_BUILD_VECTOR:
5635 assert(TypeIdx == 0 &&
"not a vector type index");
5637 case G_CONCAT_VECTORS:
5641 case G_EXTRACT_VECTOR_ELT:
5642 case G_INSERT_VECTOR_ELT:
5651 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5652 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5654 case G_SHUFFLE_VECTOR:
5660 case G_INTRINSIC_FPTRUNC_ROUND:
5670 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5671 "Not a bitcast operation");
5676 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5678 unsigned NewElemCount =
5681 if (NewElemCount == 1) {
5684 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5690 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5699 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5700 MI.eraseFromParent();
5706 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5710 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5711 MI.getFirst3RegLLTs();
5714 if (DstTy != Src1Ty)
5716 if (DstTy != Src2Ty)
5731 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5747 unsigned InputUsed[2] = {-1U, -1U};
5748 unsigned FirstMaskIdx =
High * NewElts;
5749 bool UseBuildVector =
false;
5750 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5752 int Idx = Mask[FirstMaskIdx + MaskOffset];
5757 if (
Input >= std::size(Inputs)) {
5764 Idx -=
Input * NewElts;
5768 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5769 if (InputUsed[OpNo] ==
Input) {
5772 }
else if (InputUsed[OpNo] == -1U) {
5774 InputUsed[OpNo] =
Input;
5779 if (OpNo >= std::size(InputUsed)) {
5782 UseBuildVector =
true;
5787 Ops.push_back(Idx + OpNo * NewElts);
5790 if (UseBuildVector) {
5795 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5797 int Idx = Mask[FirstMaskIdx + MaskOffset];
5802 if (
Input >= std::size(Inputs)) {
5809 Idx -=
Input * NewElts;
5813 .buildExtractVectorElement(
5814 EltTy, Inputs[
Input],
5820 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5821 }
else if (InputUsed[0] == -1U) {
5823 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5825 Register Op0 = Inputs[InputUsed[0]];
5829 : Inputs[InputUsed[1]];
5831 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5838 MI.eraseFromParent();
5851 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5857 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5860 const unsigned NumParts =
5862 : SrcTy.getNumElements();
5866 if (DstTy != NarrowTy)
5872 unsigned NumPartsLeft = NumParts;
5873 while (NumPartsLeft > 1) {
5874 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5877 .buildInstr(ScalarOpc, {NarrowTy},
5878 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5881 SplitSrcs = PartialResults;
5882 PartialResults.
clear();
5883 NumPartsLeft = SplitSrcs.
size();
5887 MI.eraseFromParent();
5892 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5893 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5896 MI.eraseFromParent();
5900 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5902 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5910 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5913 Register Acc = PartialReductions[0];
5914 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5915 if (Part == NumParts - 1) {
5917 {Acc, PartialReductions[Part]});
5920 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5924 MI.eraseFromParent();
5930 unsigned int TypeIdx,
5932 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5933 MI.getFirst3RegLLTs();
5934 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5938 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5939 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5940 "Unexpected vecreduce opcode");
5941 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5942 ? TargetOpcode::G_FADD
5943 : TargetOpcode::G_FMUL;
5946 unsigned NumParts = SrcTy.getNumElements();
5949 for (
unsigned i = 0; i < NumParts; i++)
5950 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5954 MI.eraseFromParent();
5961 unsigned ScalarOpc) {
5969 while (SplitSrcs.
size() > 1) {
5971 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
5979 SplitSrcs = std::move(PartialRdxs);
5983 MI.getOperand(1).setReg(SplitSrcs[0]);
5990 const LLT HalfTy,
const LLT AmtTy) {
5992 Register InL = MRI.createGenericVirtualRegister(HalfTy);
5993 Register InH = MRI.createGenericVirtualRegister(HalfTy);
5997 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
5998 MI.eraseFromParent();
6004 unsigned VTBits = 2 * NVTBits;
6007 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6008 if (Amt.
ugt(VTBits)) {
6010 }
else if (Amt.
ugt(NVTBits)) {
6013 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6014 }
else if (Amt == NVTBits) {
6022 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6025 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6026 if (Amt.
ugt(VTBits)) {
6028 }
else if (Amt.
ugt(NVTBits)) {
6030 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6032 }
else if (Amt == NVTBits) {
6036 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6038 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6040 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6046 if (Amt.
ugt(VTBits)) {
6048 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6049 }
else if (Amt.
ugt(NVTBits)) {
6051 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6053 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6054 }
else if (Amt == NVTBits) {
6057 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6059 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6061 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6063 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6070 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6071 MI.eraseFromParent();
6087 LLT DstTy = MRI.getType(DstReg);
6092 LLT ShiftAmtTy = MRI.getType(Amt);
6094 if (DstEltSize % 2 != 0)
6110 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6121 const unsigned NewBitSize = DstEltSize / 2;
6133 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6135 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6136 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6139 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6140 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6142 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6147 switch (
MI.getOpcode()) {
6148 case TargetOpcode::G_SHL: {
6150 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6152 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6153 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6154 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6157 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6158 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6160 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6162 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6164 ResultRegs[0] =
Lo.getReg(0);
6165 ResultRegs[1] =
Hi.getReg(0);
6168 case TargetOpcode::G_LSHR:
6169 case TargetOpcode::G_ASHR: {
6171 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6173 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6174 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6175 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6179 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6182 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6183 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6185 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6189 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6191 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6193 ResultRegs[0] =
Lo.getReg(0);
6194 ResultRegs[1] =
Hi.getReg(0);
6201 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6202 MI.eraseFromParent();
6211 LLT TargetTy,
LLT ShiftAmtTy) {
6214 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6216 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6217 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6218 const bool NeedsInterWordShift = ShiftBits != 0;
6221 case TargetOpcode::G_SHL: {
6224 if (PartIdx < ShiftWords)
6227 unsigned SrcIdx = PartIdx - ShiftWords;
6228 if (!NeedsInterWordShift)
6229 return SrcParts[SrcIdx];
6234 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6238 return Hi.getReg(0);
6241 case TargetOpcode::G_LSHR: {
6242 unsigned SrcIdx = PartIdx + ShiftWords;
6243 if (SrcIdx >= NumParts)
6245 if (!NeedsInterWordShift)
6246 return SrcParts[SrcIdx];
6250 if (SrcIdx + 1 < NumParts) {
6251 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6255 return Lo.getReg(0);
6258 case TargetOpcode::G_ASHR: {
6260 unsigned SrcIdx = PartIdx + ShiftWords;
6261 if (SrcIdx >= NumParts)
6263 if (!NeedsInterWordShift)
6264 return SrcParts[SrcIdx];
6269 (SrcIdx == NumParts - 1)
6273 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6295 unsigned MainOpcode =
6296 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6300 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6309 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6310 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6312 auto IsZeroBitShift =
6320 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6321 : TargetOpcode::G_SHL;
6324 auto TargetBitsConst =
6326 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6331 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6336 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6338 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6342 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6355 LLT DstTy = MRI.getType(DstReg);
6359 const unsigned NumParts = DstBits / TargetBits;
6361 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6371 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6372 MI.eraseFromParent();
6377 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6378 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6384 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6388 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6391 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6392 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6396 for (
unsigned I = 0;
I < NumParts; ++
I)
6398 Params, TargetTy, ShiftAmtTy);
6400 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6401 MI.eraseFromParent();
6410 LLT DstTy = MRI.getType(DstReg);
6411 LLT ShiftAmtTy = MRI.getType(AmtReg);
6415 const unsigned NumParts = DstBits / TargetBits;
6417 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6434 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6446 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6447 auto TargetBitsLog2Const =
6448 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6449 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6452 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6454 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6462 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6463 auto TargetBitsMinusOneConst =
6464 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6466 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6467 TargetBitsMinusOneConst)
6470 FillValue = ZeroReg;
6478 for (
unsigned I = 0;
I < NumParts; ++
I) {
6480 Register InBoundsResult = FillValue;
6490 for (
unsigned K = 0; K < NumParts; ++K) {
6491 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6493 WordShift, WordShiftKConst);
6505 switch (
MI.getOpcode()) {
6506 case TargetOpcode::G_SHL:
6507 MainSrcIdx = (int)
I - (
int)K;
6508 CarrySrcIdx = MainSrcIdx - 1;
6510 case TargetOpcode::G_LSHR:
6511 case TargetOpcode::G_ASHR:
6512 MainSrcIdx = (int)
I + (
int)K;
6513 CarrySrcIdx = MainSrcIdx + 1;
6521 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6522 Register MainOp = SrcParts[MainSrcIdx];
6526 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6527 CarryOp = SrcParts[CarrySrcIdx];
6528 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6529 CarrySrcIdx >= (
int)NumParts)
6530 CarryOp = FillValue;
6536 ResultForK = FillValue;
6542 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6549 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6553 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6554 MI.eraseFromParent();
6561 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6564 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6579 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6584 "getNeutralElementForVecReduce called with invalid opcode!");
6585 case TargetOpcode::G_VECREDUCE_ADD:
6586 case TargetOpcode::G_VECREDUCE_OR:
6587 case TargetOpcode::G_VECREDUCE_XOR:
6588 case TargetOpcode::G_VECREDUCE_UMAX:
6590 case TargetOpcode::G_VECREDUCE_MUL:
6592 case TargetOpcode::G_VECREDUCE_AND:
6593 case TargetOpcode::G_VECREDUCE_UMIN:
6596 case TargetOpcode::G_VECREDUCE_SMAX:
6599 case TargetOpcode::G_VECREDUCE_SMIN:
6602 case TargetOpcode::G_VECREDUCE_FADD:
6604 case TargetOpcode::G_VECREDUCE_FMUL:
6606 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6607 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6608 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6609 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6617 unsigned Opc =
MI.getOpcode();
6619 case TargetOpcode::G_IMPLICIT_DEF:
6620 case TargetOpcode::G_LOAD: {
6628 case TargetOpcode::G_STORE:
6635 case TargetOpcode::G_AND:
6636 case TargetOpcode::G_OR:
6637 case TargetOpcode::G_XOR:
6638 case TargetOpcode::G_ADD:
6639 case TargetOpcode::G_SUB:
6640 case TargetOpcode::G_MUL:
6641 case TargetOpcode::G_FADD:
6642 case TargetOpcode::G_FSUB:
6643 case TargetOpcode::G_FMUL:
6644 case TargetOpcode::G_FDIV:
6645 case TargetOpcode::G_FCOPYSIGN:
6646 case TargetOpcode::G_UADDSAT:
6647 case TargetOpcode::G_USUBSAT:
6648 case TargetOpcode::G_SADDSAT:
6649 case TargetOpcode::G_SSUBSAT:
6650 case TargetOpcode::G_SMIN:
6651 case TargetOpcode::G_SMAX:
6652 case TargetOpcode::G_UMIN:
6653 case TargetOpcode::G_UMAX:
6654 case TargetOpcode::G_FMINNUM:
6655 case TargetOpcode::G_FMAXNUM:
6656 case TargetOpcode::G_FMINNUM_IEEE:
6657 case TargetOpcode::G_FMAXNUM_IEEE:
6658 case TargetOpcode::G_FMINIMUM:
6659 case TargetOpcode::G_FMAXIMUM:
6660 case TargetOpcode::G_FMINIMUMNUM:
6661 case TargetOpcode::G_FMAXIMUMNUM:
6662 case TargetOpcode::G_STRICT_FADD:
6663 case TargetOpcode::G_STRICT_FSUB:
6664 case TargetOpcode::G_STRICT_FMUL:
6665 case TargetOpcode::G_SHL:
6666 case TargetOpcode::G_ASHR:
6667 case TargetOpcode::G_LSHR: {
6675 case TargetOpcode::G_FMA:
6676 case TargetOpcode::G_STRICT_FMA:
6677 case TargetOpcode::G_FSHR:
6678 case TargetOpcode::G_FSHL: {
6687 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6688 case TargetOpcode::G_EXTRACT:
6695 case TargetOpcode::G_INSERT:
6696 case TargetOpcode::G_INSERT_VECTOR_ELT:
6697 case TargetOpcode::G_FREEZE:
6698 case TargetOpcode::G_FNEG:
6699 case TargetOpcode::G_FABS:
6700 case TargetOpcode::G_FSQRT:
6701 case TargetOpcode::G_FCEIL:
6702 case TargetOpcode::G_FFLOOR:
6703 case TargetOpcode::G_FNEARBYINT:
6704 case TargetOpcode::G_FRINT:
6705 case TargetOpcode::G_INTRINSIC_ROUND:
6706 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6707 case TargetOpcode::G_INTRINSIC_TRUNC:
6708 case TargetOpcode::G_BITREVERSE:
6709 case TargetOpcode::G_BSWAP:
6710 case TargetOpcode::G_FCANONICALIZE:
6711 case TargetOpcode::G_SEXT_INREG:
6712 case TargetOpcode::G_ABS:
6713 case TargetOpcode::G_CTLZ:
6714 case TargetOpcode::G_CTPOP:
6722 case TargetOpcode::G_SELECT: {
6723 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6725 if (!CondTy.isScalar() ||
6731 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6733 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6738 if (CondTy.isVector())
6748 case TargetOpcode::G_UNMERGE_VALUES:
6750 case TargetOpcode::G_PHI:
6752 case TargetOpcode::G_SHUFFLE_VECTOR:
6754 case TargetOpcode::G_BUILD_VECTOR: {
6756 for (
auto Op :
MI.uses()) {
6764 MIRBuilder.buildDeleteTrailingVectorElements(
6765 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6766 MI.eraseFromParent();
6769 case TargetOpcode::G_SEXT:
6770 case TargetOpcode::G_ZEXT:
6771 case TargetOpcode::G_ANYEXT:
6772 case TargetOpcode::G_TRUNC:
6773 case TargetOpcode::G_FPTRUNC:
6774 case TargetOpcode::G_FPEXT:
6775 case TargetOpcode::G_FPTOSI:
6776 case TargetOpcode::G_FPTOUI:
6777 case TargetOpcode::G_FPTOSI_SAT:
6778 case TargetOpcode::G_FPTOUI_SAT:
6779 case TargetOpcode::G_SITOFP:
6780 case TargetOpcode::G_UITOFP: {
6788 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6792 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6800 case TargetOpcode::G_ICMP:
6801 case TargetOpcode::G_FCMP: {
6810 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6815 case TargetOpcode::G_BITCAST: {
6819 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6820 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6836 case TargetOpcode::G_VECREDUCE_FADD:
6837 case TargetOpcode::G_VECREDUCE_FMUL:
6838 case TargetOpcode::G_VECREDUCE_ADD:
6839 case TargetOpcode::G_VECREDUCE_MUL:
6840 case TargetOpcode::G_VECREDUCE_AND:
6841 case TargetOpcode::G_VECREDUCE_OR:
6842 case TargetOpcode::G_VECREDUCE_XOR:
6843 case TargetOpcode::G_VECREDUCE_SMAX:
6844 case TargetOpcode::G_VECREDUCE_SMIN:
6845 case TargetOpcode::G_VECREDUCE_UMAX:
6846 case TargetOpcode::G_VECREDUCE_UMIN: {
6847 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6849 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6850 auto NeutralElement = getNeutralElementForVecReduce(
6856 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6857 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6858 NeutralElement, Idx);
6862 MO.
setReg(NewVec.getReg(0));
6874 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6876 unsigned MaskNumElts = Mask.size();
6877 unsigned SrcNumElts = SrcTy.getNumElements();
6880 if (MaskNumElts == SrcNumElts)
6883 if (MaskNumElts < SrcNumElts) {
6891 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6892 MI.getOperand(1).getReg(),
6893 MI.getOperand(2).getReg(), NewMask);
6894 MI.eraseFromParent();
6899 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6900 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6908 MOps1[0] =
MI.getOperand(1).getReg();
6909 MOps2[0] =
MI.getOperand(2).getReg();
6911 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6912 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6916 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6918 if (Idx >=
static_cast<int>(SrcNumElts))
6919 Idx += PaddedMaskNumElts - SrcNumElts;
6924 if (MaskNumElts != PaddedMaskNumElts) {
6926 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6929 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6931 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6936 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6939 MI.eraseFromParent();
6945 unsigned int TypeIdx,
LLT MoreTy) {
6946 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6948 unsigned NumElts = DstTy.getNumElements();
6951 if (DstTy.isVector() && Src1Ty.isVector() &&
6952 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6960 if (DstTy != Src1Ty || DstTy != Src2Ty)
6968 for (
unsigned I = 0;
I != NumElts; ++
I) {
6970 if (Idx <
static_cast<int>(NumElts))
6973 NewMask[
I] = Idx - NumElts + WidenNumElts;
6977 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6978 MI.getOperand(1).getReg(),
6979 MI.getOperand(2).getReg(), NewMask);
6980 MI.eraseFromParent();
6989 unsigned SrcParts = Src1Regs.
size();
6990 unsigned DstParts = DstRegs.
size();
6992 unsigned DstIdx = 0;
6994 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
6995 DstRegs[DstIdx] = FactorSum;
7000 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7002 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7003 i <= std::min(DstIdx, SrcParts - 1); ++i) {
7005 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7009 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7010 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7012 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7022 if (DstIdx != DstParts - 1) {
7023 MachineInstrBuilder Uaddo =
7024 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
7025 FactorSum = Uaddo.
getReg(0);
7026 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7027 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7028 MachineInstrBuilder Uaddo =
7029 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
7030 FactorSum = Uaddo.
getReg(0);
7031 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7032 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7036 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7037 for (
unsigned i = 2; i < Factors.
size(); ++i)
7038 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7041 CarrySumPrevDstIdx = CarrySum;
7042 DstRegs[DstIdx] = FactorSum;
7054 LLT DstType = MRI.getType(DstReg);
7056 if (DstType.isVector())
7059 unsigned Opcode =
MI.getOpcode();
7060 unsigned OpO, OpE, OpF;
7062 case TargetOpcode::G_SADDO:
7063 case TargetOpcode::G_SADDE:
7064 case TargetOpcode::G_UADDO:
7065 case TargetOpcode::G_UADDE:
7066 case TargetOpcode::G_ADD:
7067 OpO = TargetOpcode::G_UADDO;
7068 OpE = TargetOpcode::G_UADDE;
7069 OpF = TargetOpcode::G_UADDE;
7070 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7071 OpF = TargetOpcode::G_SADDE;
7073 case TargetOpcode::G_SSUBO:
7074 case TargetOpcode::G_SSUBE:
7075 case TargetOpcode::G_USUBO:
7076 case TargetOpcode::G_USUBE:
7077 case TargetOpcode::G_SUB:
7078 OpO = TargetOpcode::G_USUBO;
7079 OpE = TargetOpcode::G_USUBE;
7080 OpF = TargetOpcode::G_USUBE;
7081 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7082 OpF = TargetOpcode::G_SSUBE;
7089 unsigned NumDefs =
MI.getNumExplicitDefs();
7090 Register Src1 =
MI.getOperand(NumDefs).getReg();
7091 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7094 CarryDst =
MI.getOperand(1).getReg();
7095 if (
MI.getNumOperands() == NumDefs + 3)
7096 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7098 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7099 LLT LeftoverTy, DummyTy;
7101 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7106 int NarrowParts = Src1Regs.
size();
7107 Src1Regs.
append(Src1Left);
7108 Src2Regs.
append(Src2Left);
7111 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7113 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7116 if (i == e - 1 && CarryDst)
7117 CarryOut = CarryDst;
7119 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7122 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7123 {Src1Regs[i], Src2Regs[i]});
7124 }
else if (i == e - 1) {
7125 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7126 {Src1Regs[i], Src2Regs[i], CarryIn});
7128 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7129 {Src1Regs[i], Src2Regs[i], CarryIn});
7135 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7136 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7137 ArrayRef(DstRegs).drop_front(NarrowParts));
7139 MI.eraseFromParent();
7145 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7147 LLT Ty = MRI.getType(DstReg);
7151 unsigned Size = Ty.getSizeInBits();
7153 if (
Size % NarrowSize != 0)
7156 unsigned NumParts =
Size / NarrowSize;
7157 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7158 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7164 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7168 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7169 MI.eraseFromParent();
7179 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7182 LLT SrcTy = MRI.getType(Src);
7193 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7206 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7209 if (SizeOp1 % NarrowSize != 0)
7211 int NumParts = SizeOp1 / NarrowSize;
7214 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7218 uint64_t OpStart =
MI.getOperand(2).getImm();
7219 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7220 for (
int i = 0; i < NumParts; ++i) {
7221 unsigned SrcStart = i * NarrowSize;
7223 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7226 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7234 int64_t ExtractOffset;
7236 if (OpStart < SrcStart) {
7238 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7240 ExtractOffset = OpStart - SrcStart;
7241 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7245 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7247 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7248 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7255 if (MRI.getType(DstReg).isVector())
7256 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7257 else if (DstRegs.
size() > 1)
7258 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7261 MI.eraseFromParent();
7273 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7275 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7278 SrcRegs.
append(LeftoverRegs);
7282 uint64_t OpStart =
MI.getOperand(3).getImm();
7283 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7284 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7285 unsigned DstStart =
I * NarrowSize;
7287 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7295 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7297 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7301 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7309 int64_t ExtractOffset, InsertOffset;
7311 if (OpStart < DstStart) {
7313 ExtractOffset = DstStart - OpStart;
7314 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7316 InsertOffset = OpStart - DstStart;
7319 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7323 if (ExtractOffset != 0 || SegSize != OpSize) {
7325 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7326 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7329 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7330 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7338 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7341 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7343 MI.eraseFromParent();
7351 LLT DstTy = MRI.getType(DstReg);
7353 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7359 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7360 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7364 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7365 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7368 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7369 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7370 {Src0Regs[I], Src1Regs[I]});
7374 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7377 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7378 DstLeftoverRegs.
push_back(Inst.getReg(0));
7381 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7382 LeftoverTy, DstLeftoverRegs);
7384 MI.eraseFromParent();
7394 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7396 LLT DstTy = MRI.getType(DstReg);
7401 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7402 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7403 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7405 MI.eraseFromParent();
7415 Register CondReg =
MI.getOperand(1).getReg();
7416 LLT CondTy = MRI.getType(CondReg);
7421 LLT DstTy = MRI.getType(DstReg);
7427 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7428 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7432 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7433 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7436 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7438 CondReg, Src1Regs[
I], Src2Regs[
I]);
7442 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7444 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7448 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7449 LeftoverTy, DstLeftoverRegs);
7451 MI.eraseFromParent();
7461 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7464 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7465 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7468 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7470 auto C_0 =
B.buildConstant(NarrowTy, 0);
7472 UnmergeSrc.getReg(1), C_0);
7473 auto LoCTLZ = IsUndef ?
7474 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7475 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7476 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7477 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7478 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7479 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7481 MI.eraseFromParent();
7494 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7497 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7498 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7501 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7503 auto C_0 =
B.buildConstant(NarrowTy, 0);
7505 UnmergeSrc.getReg(0), C_0);
7506 auto HiCTTZ = IsUndef ?
7507 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7508 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7509 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7510 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7511 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7512 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7514 MI.eraseFromParent();
7527 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7530 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7531 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7533 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7534 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7535 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7537 MI.eraseFromParent();
7552 LLT ExpTy = MRI.getType(ExpReg);
7557 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7558 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7559 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7560 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7562 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7564 MI.getOperand(2).setReg(Trunc.getReg(0));
7571 unsigned Opc =
MI.getOpcode();
7574 auto QAction = LI.getAction(Q).Action;
7580 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7583 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7587 case TargetOpcode::G_CTLZ: {
7588 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7589 unsigned Len = SrcTy.getSizeInBits();
7591 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7593 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7594 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7597 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7598 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7599 MI.eraseFromParent();
7615 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7616 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7619 Op = MIBOp.getReg(0);
7624 MI.eraseFromParent();
7627 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7630 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7634 case TargetOpcode::G_CTTZ: {
7635 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7637 unsigned Len = SrcTy.getSizeInBits();
7638 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7641 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7642 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7645 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7646 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7647 MI.eraseFromParent();
7654 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7655 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7657 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7658 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7659 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7660 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7663 MI.eraseFromParent();
7667 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7668 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7672 case TargetOpcode::G_CTPOP: {
7674 LLT Ty = MRI.getType(SrcReg);
7675 unsigned Size = Ty.getSizeInBits();
7683 auto C_1 =
B.buildConstant(Ty, 1);
7684 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7686 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7687 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7688 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7692 auto C_2 =
B.buildConstant(Ty, 2);
7693 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7695 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7696 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7697 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7698 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7705 auto C_4 =
B.buildConstant(Ty, 4);
7706 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7707 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7709 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7710 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7712 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7718 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7720 auto IsMulSupported = [
this](
const LLT Ty) {
7721 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7724 if (IsMulSupported(Ty)) {
7725 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7726 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7728 auto ResTmp = B8Count;
7729 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7730 auto ShiftC =
B.buildConstant(Ty, Shift);
7731 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7732 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7734 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7736 MI.eraseFromParent();
7757 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7758 LLT Ty = MRI.getType(Dst);
7759 LLT ShTy = MRI.getType(Z);
7766 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7767 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7772 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7773 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7777 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7790 MI.eraseFromParent();
7796 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7797 LLT Ty = MRI.getType(Dst);
7798 LLT ShTy = MRI.getType(Z);
7801 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7811 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7812 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7813 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7814 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7815 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7819 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7822 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7825 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7827 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7828 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7829 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7832 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7834 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7836 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7839 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7840 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7845 MI.eraseFromParent();
7856 LLT Ty = MRI.getType(Dst);
7857 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7859 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7860 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7863 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7864 return lowerFunnelShiftAsShifts(
MI);
7868 if (Result == UnableToLegalize)
7869 return lowerFunnelShiftAsShifts(
MI);
7874 auto [Dst, Src] =
MI.getFirst2Regs();
7875 LLT DstTy = MRI.getType(Dst);
7876 LLT SrcTy = MRI.getType(Src);
7880 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7888 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7892 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7896 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7901 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7902 {UnmergeSrc.getReg(0)});
7903 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7904 {UnmergeSrc.getReg(1)});
7907 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7909 MI.eraseFromParent();
7926 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7930 LLT DstTy = MRI.getType(DstReg);
7931 LLT SrcTy = MRI.getType(SrcReg);
7939 SrcTy.getElementCount().divideCoefficientBy(2));
7952 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7964 MI.eraseFromParent();
7973 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7974 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
7975 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7976 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7977 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
7978 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
7979 MI.eraseFromParent();
7984 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7986 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
7987 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7992 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7993 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
7995 return lowerRotateWithReverseRotate(
MI);
7998 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7999 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8000 bool IsFShLegal =
false;
8001 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8002 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8006 MI.eraseFromParent();
8011 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8014 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8019 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8020 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8021 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8027 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8028 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8030 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8036 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8037 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8039 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8041 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8045 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
8046 MI.eraseFromParent();
8054 auto [Dst, Src] =
MI.getFirst2Regs();
8059 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8087 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8100 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8104 MI.eraseFromParent();
8112 auto [Dst, Src] =
MI.getFirst2Regs();
8117 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8130 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8132 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8137 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8139 MI.eraseFromParent();
8147 auto [Dst, Src] =
MI.getFirst2Regs();
8151 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8162 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8163 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8165 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8172 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8173 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8174 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8176 MI.eraseFromParent();
8186 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8192 MI.eraseFromParent();
8197 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8200 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8201 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8202 MIRBuilder.buildSelect(Dst, Src, True, False);
8203 MI.eraseFromParent();
8207 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8227 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8234 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8235 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8236 MIRBuilder.buildSelect(Dst, Src, True, False);
8237 MI.eraseFromParent();
8241 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8264 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8265 MI.eraseFromParent();
8273 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8277 if (SrcTy !=
S64 && SrcTy !=
S32)
8279 if (DstTy !=
S32 && DstTy !=
S64)
8306 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8308 MI.eraseFromParent();
8313 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8318 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8325 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8327 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8328 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8330 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8331 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8333 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8335 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8336 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8337 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8340 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8341 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8342 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8344 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8347 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8352 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8353 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8359 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8361 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8362 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8364 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8369 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8370 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8372 MI.eraseFromParent();
8378 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8380 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8381 unsigned SatWidth = DstTy.getScalarSizeInBits();
8385 APInt MinInt, MaxInt;
8408 if (AreExactFloatBounds) {
8410 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8412 SrcTy.changeElementSize(1), Src, MaxC);
8413 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8415 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8425 MI.eraseFromParent();
8430 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8432 DstTy.changeElementSize(1), Src, Src);
8435 MI.eraseFromParent();
8442 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8451 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8462 MI.eraseFromParent();
8468 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8470 DstTy.changeElementSize(1), Src, Src);
8472 MI.eraseFromParent();
8482 auto [Dst, Src] =
MI.getFirst2Regs();
8484 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8486 if (MRI.getType(Src).isVector())
8490 unsigned Flags =
MI.getFlags();
8493 MI.eraseFromParent();
8497 const unsigned ExpMask = 0x7ff;
8498 const unsigned ExpBiasf64 = 1023;
8499 const unsigned ExpBiasf16 = 15;
8528 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8588 MI.eraseFromParent();
8594 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8598 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8605 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8606 LLT Ty = MRI.getType(Dst);
8608 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8609 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8610 MI.eraseFromParent();
8616 case TargetOpcode::G_SMIN:
8618 case TargetOpcode::G_SMAX:
8620 case TargetOpcode::G_UMIN:
8622 case TargetOpcode::G_UMAX:
8630 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8635 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8636 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8638 MI.eraseFromParent();
8647 LLT DstTy = MRI.getType(Dst);
8648 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8658 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8659 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8661 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8664 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8665 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8666 if (TLI.preferSelectsOverBooleanArithmetic(
8669 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8670 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8672 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8673 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8679 unsigned BoolExtOp =
8681 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8682 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8686 MI.eraseFromParent();
8692 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8693 const int Src0Size = Src0Ty.getScalarSizeInBits();
8694 const int Src1Size = Src1Ty.getScalarSizeInBits();
8699 auto NotSignBitMask =
MIRBuilder.buildConstant(
8704 if (Src0Ty == Src1Ty) {
8705 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8706 }
else if (Src0Size > Src1Size) {
8707 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8708 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8709 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8710 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8712 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8713 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8714 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8715 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8721 unsigned Flags =
MI.getFlags();
8728 MI.eraseFromParent();
8739 switch (
MI.getOpcode()) {
8740 case TargetOpcode::G_FMINNUM:
8741 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8743 case TargetOpcode::G_FMINIMUMNUM:
8744 NewOp = TargetOpcode::G_FMINNUM;
8746 case TargetOpcode::G_FMAXNUM:
8747 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8749 case TargetOpcode::G_FMAXIMUMNUM:
8750 NewOp = TargetOpcode::G_FMAXNUM;
8756 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8757 LLT Ty = MRI.getType(Dst);
8767 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8770 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8775 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8776 MI.eraseFromParent();
8783 LLT Ty = MRI.getType(DstReg);
8784 unsigned Flags =
MI.getFlags();
8789 MI.eraseFromParent();
8795 auto [DstReg,
X] =
MI.getFirst2Regs();
8796 const unsigned Flags =
MI.getFlags();
8797 const LLT Ty = MRI.getType(DstReg);
8809 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8811 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8816 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8817 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8818 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8819 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8821 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8823 MI.eraseFromParent();
8828 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8829 unsigned Flags =
MI.getFlags();
8830 LLT Ty = MRI.getType(DstReg);
8837 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8838 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8841 SrcReg, Zero, Flags);
8843 SrcReg, Trunc, Flags);
8847 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8848 MI.eraseFromParent();
8854 const unsigned NumOps =
MI.getNumOperands();
8855 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8856 unsigned PartSize = Src0Ty.getSizeInBits();
8861 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8862 const unsigned Offset = (
I - 1) * PartSize;
8865 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8868 MRI.createGenericVirtualRegister(WideTy);
8871 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8872 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8873 ResultReg = NextResult;
8876 if (DstTy.isPointer()) {
8877 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8878 DstTy.getAddressSpace())) {
8886 MI.eraseFromParent();
8892 const unsigned NumDst =
MI.getNumOperands() - 1;
8893 Register SrcReg =
MI.getOperand(NumDst).getReg();
8894 Register Dst0Reg =
MI.getOperand(0).getReg();
8895 LLT DstTy = MRI.getType(Dst0Reg);
8904 LLT IntTy = MRI.getType(SrcReg);
8909 unsigned Offset = DstSize;
8910 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
8912 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
8916 MI.eraseFromParent();
8935 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
8936 InsertVal =
MI.getOperand(2).getReg();
8938 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
8940 LLT VecTy = MRI.getType(SrcVec);
8950 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
8951 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
8953 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
8956 MI.eraseFromParent();
8961 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
8972 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
8979 int64_t
Offset = IdxVal * EltBytes;
8990 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
8993 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
8995 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
8998 MI.eraseFromParent();
9004 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9005 MI.getFirst3RegLLTs();
9013 for (
int Idx : Mask) {
9015 if (!Undef.isValid())
9016 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
9021 if (Src0Ty.isScalar()) {
9022 BuildVec.
push_back(Idx == 0 ? Src0Reg : Src1Reg);
9024 int NumElts = Src0Ty.getNumElements();
9025 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9026 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9027 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9028 auto Extract =
MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK);
9033 if (DstTy.isVector())
9034 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9037 MI.eraseFromParent();
9043 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9044 MI.getFirst4RegLLTs();
9046 if (VecTy.isScalableVector())
9062 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9065 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9068 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9071 std::optional<APInt> PassthruSplatVal =
9074 if (PassthruSplatVal.has_value()) {
9076 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9077 }
else if (HasPassthru) {
9078 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9079 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9085 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9089 unsigned NumElmts = VecTy.getNumElements();
9090 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9092 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9095 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9098 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9103 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9105 if (HasPassthru &&
I == NumElmts - 1) {
9108 auto AllLanesSelected =
MIRBuilder.buildICmp(
9110 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9111 {OutPos, EndOfVector});
9115 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9117 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9122 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9124 MI.eraseFromParent();
9135 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9141 if (Alignment >
Align(1)) {
9144 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9153 const auto &MF = *
MI.getMF();
9159 Register AllocSize =
MI.getOperand(1).getReg();
9162 LLT PtrTy = MRI.getType(Dst);
9163 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9170 MI.eraseFromParent();
9176 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9181 MI.eraseFromParent();
9187 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9192 MI.eraseFromParent();
9198 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9199 unsigned Offset =
MI.getOperand(2).getImm();
9202 if (SrcTy.isVector()) {
9203 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9204 unsigned DstSize = DstTy.getSizeInBits();
9206 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9207 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9209 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9213 for (
unsigned Idx =
Offset / SrcEltSize;
9214 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9215 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9217 if (SubVectorElts.
size() == 1)
9218 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9220 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9222 MI.eraseFromParent();
9227 if (DstTy.isScalar() &&
9228 (SrcTy.isScalar() ||
9229 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9230 LLT SrcIntTy = SrcTy;
9231 if (!SrcTy.isScalar()) {
9233 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9240 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9244 MI.eraseFromParent();
9252 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9255 LLT DstTy = MRI.getType(Src);
9256 LLT InsertTy = MRI.getType(InsertSrc);
9264 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9266 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9270 for (; Idx <
Offset / EltSize; ++Idx) {
9271 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9276 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9277 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9279 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9288 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9291 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9292 MI.eraseFromParent();
9306 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9310 LLT IntDstTy = DstTy;
9314 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9319 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9325 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9331 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9332 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9333 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9336 MI.eraseFromParent();
9342 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9343 MI.getFirst4RegLLTs();
9344 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9347 LLT BoolTy = Dst1Ty;
9349 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9366 auto ResultLowerThanLHS =
9371 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9374 MI.eraseFromParent();
9380 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9381 const LLT Ty = MRI.getType(Res);
9384 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9385 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9386 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9397 MI.eraseFromParent();
9402 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9403 const LLT Ty = MRI.getType(Res);
9406 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9407 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9408 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9413 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9418 MI.eraseFromParent();
9424 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9425 LLT Ty = MRI.getType(Res);
9429 switch (
MI.getOpcode()) {
9432 case TargetOpcode::G_UADDSAT:
9435 BaseOp = TargetOpcode::G_ADD;
9437 case TargetOpcode::G_SADDSAT:
9440 BaseOp = TargetOpcode::G_ADD;
9442 case TargetOpcode::G_USUBSAT:
9445 BaseOp = TargetOpcode::G_SUB;
9447 case TargetOpcode::G_SSUBSAT:
9450 BaseOp = TargetOpcode::G_SUB;
9465 uint64_t NumBits = Ty.getScalarSizeInBits();
9476 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9484 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9489 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9490 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9493 MI.eraseFromParent();
9499 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9500 LLT Ty = MRI.getType(Res);
9504 unsigned OverflowOp;
9505 switch (
MI.getOpcode()) {
9508 case TargetOpcode::G_UADDSAT:
9511 OverflowOp = TargetOpcode::G_UADDO;
9513 case TargetOpcode::G_SADDSAT:
9516 OverflowOp = TargetOpcode::G_SADDO;
9518 case TargetOpcode::G_USUBSAT:
9521 OverflowOp = TargetOpcode::G_USUBO;
9523 case TargetOpcode::G_SSUBSAT:
9526 OverflowOp = TargetOpcode::G_SSUBO;
9531 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9532 Register Tmp = OverflowRes.getReg(0);
9533 Register Ov = OverflowRes.getReg(1);
9542 uint64_t NumBits = Ty.getScalarSizeInBits();
9543 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9544 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9547 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9555 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9559 MI.eraseFromParent();
9565 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9566 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9567 "Expected shlsat opcode!");
9568 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9569 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9570 LLT Ty = MRI.getType(Res);
9574 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9575 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9584 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9589 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9591 MI.eraseFromParent();
9596 auto [Dst, Src] =
MI.getFirst2Regs();
9597 const LLT Ty = MRI.getType(Src);
9598 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9599 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9602 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9603 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9604 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9605 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9608 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9610 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9611 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9612 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9614 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9615 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9616 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9618 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9619 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9620 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9622 Res.getInstr()->getOperand(0).setReg(Dst);
9624 MI.eraseFromParent();
9631 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9634 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9635 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9636 return B.buildOr(Dst,
LHS,
RHS);
9641 auto [Dst, Src] =
MI.getFirst2Regs();
9642 const LLT SrcTy = MRI.getType(Src);
9643 unsigned Size = SrcTy.getScalarSizeInBits();
9644 unsigned VSize = SrcTy.getSizeInBits();
9647 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9648 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9649 {LLT::fixed_vector(VSize / 8, 8),
9650 LLT::fixed_vector(VSize / 8, 8)}}))) {
9655 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9656 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9657 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9661 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9684 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9688 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9691 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9695 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9699 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9704 MI.eraseFromParent();
9712 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9713 int NameOpIdx = IsRead ? 1 : 0;
9714 int ValRegIndex = IsRead ? 0 : 1;
9716 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9717 const LLT Ty = MRI.getType(ValReg);
9719 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9726 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9727 Fn,
MI.getDebugLoc()));
9731 MI.eraseFromParent();
9740 MI.eraseFromParent();
9746 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9747 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9749 LLT OrigTy = MRI.getType(Result);
9753 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9754 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9756 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9758 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9759 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9762 MI.eraseFromParent();
9768 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9773 MI.eraseFromParent();
9778 MI.eraseFromParent();
9785 unsigned BitSize = SrcTy.getScalarSizeInBits();
9789 if (SrcTy.isVector())
9790 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9791 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9797 APInt ExpMask = Inf;
9803 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9804 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9805 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9806 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9807 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9809 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9813 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9815 LLT DstTyCopy = DstTy;
9817 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9845 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9848 Mask &= ~PartialCheck;
9857 else if (PartialCheck ==
fcZero)
9869 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9870 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9873 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9875 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9876 appendToRes(SubnormalRes);
9883 else if (PartialCheck ==
fcInf)
9888 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9895 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
9896 if (PartialCheck ==
fcNan) {
9900 }
else if (PartialCheck ==
fcQNan) {
9910 Abs, InfWithQnanBitC);
9911 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
9918 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
9920 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
9921 APInt MaxExpMinusOne = ExpMask - ExpLSB;
9924 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
9926 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
9929 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
9930 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
9932 appendToRes(NormalRes);
9936 MI.eraseFromParent();
9942 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
9943 MI.getFirst4RegLLTs();
9945 bool IsEltPtr = DstTy.isPointerOrPointerVector();
9949 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
9950 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
9954 if (MaskTy.isScalar()) {
9962 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
9966 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
9968 if (DstTy.isVector()) {
9970 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
9971 MaskReg = ShufSplat.getReg(0);
9976 }
else if (!DstTy.isVector()) {
9981 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
9985 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
9986 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
9987 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
9994 MI.eraseFromParent();
10000 unsigned Opcode =
MI.getOpcode();
10003 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10004 : TargetOpcode::G_UDIV,
10005 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10007 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10008 : TargetOpcode::G_UREM,
10009 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10010 MI.eraseFromParent();
10020 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10024 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10027 MI.eraseFromParent();
10037 Register SrcReg =
MI.getOperand(1).getReg();
10038 LLT Ty = MRI.getType(SrcReg);
10039 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10042 MI.eraseFromParent();
10048 Register SrcReg =
MI.getOperand(1).getReg();
10049 Register DestReg =
MI.getOperand(0).getReg();
10051 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10052 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10055 MI.eraseFromParent();
10061 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10062 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10063 "Expected G_ABDS or G_ABDU instruction");
10065 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10066 LLT Ty = MRI.getType(LHS);
10076 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10078 MI.eraseFromParent();
10084 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10085 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10086 "Expected G_ABDS or G_ABDU instruction");
10088 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10089 LLT Ty = MRI.getType(LHS);
10094 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10095 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10096 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10098 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10099 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10101 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10103 MI.eraseFromParent();
10108 Register SrcReg =
MI.getOperand(1).getReg();
10109 Register DstReg =
MI.getOperand(0).getReg();
10111 LLT Ty = MRI.getType(DstReg);
10119 MI.eraseFromParent();
10125 Register SrcReg =
MI.getOperand(1).getReg();
10126 LLT SrcTy = MRI.getType(SrcReg);
10127 LLT DstTy = MRI.getType(SrcReg);
10130 if (SrcTy.isScalar()) {
10135 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10146 Register ListPtr =
MI.getOperand(1).getReg();
10147 LLT PtrTy = MRI.getType(ListPtr);
10154 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10156 const Align A(
MI.getOperand(2).getImm());
10158 if (
A > TLI.getMinStackArgumentAlignment()) {
10160 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10161 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10162 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10163 VAList = AndDst.getReg(0);
10170 LLT LLTTy = MRI.getType(Dst);
10173 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10174 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10179 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10181 Align EltAlignment =
DL.getABITypeAlign(Ty);
10184 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10186 MI.eraseFromParent();
10201 unsigned Limit,
const MemOp &
Op,
10202 unsigned DstAS,
unsigned SrcAS,
10203 const AttributeList &FuncAttributes,
10205 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10215 if (
Op.isFixedDstAlign())
10216 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10219 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10223 unsigned NumMemOps = 0;
10226 unsigned TySize = Ty.getSizeInBytes();
10227 while (TySize >
Size) {
10236 assert(NewTySize > 0 &&
"Could not find appropriate type");
10243 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10245 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10251 TySize = NewTySize;
10255 if (++NumMemOps > Limit)
10258 MemOps.push_back(Ty);
10268 unsigned NumBits = Ty.getScalarSizeInBits();
10270 if (!Ty.isVector() && ValVRegAndVal) {
10271 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10279 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10300 uint64_t KnownLen,
Align Alignment,
10302 auto &MF = *
MI.getParent()->getParent();
10307 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10309 bool DstAlignCanChange =
false;
10313 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10315 DstAlignCanChange =
true;
10317 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10318 std::vector<LLT> MemOps;
10320 const auto &DstMMO = **
MI.memoperands_begin();
10321 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10324 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10335 if (DstAlignCanChange) {
10338 Align NewAlign =
DL.getABITypeAlign(IRTy);
10339 if (NewAlign > Alignment) {
10340 Alignment = NewAlign;
10348 MachineIRBuilder MIB(
MI);
10350 LLT LargestTy = MemOps[0];
10351 for (
unsigned i = 1; i < MemOps.size(); i++)
10353 LargestTy = MemOps[i];
10365 LLT PtrTy = MRI.getType(Dst);
10366 unsigned DstOff = 0;
10367 unsigned Size = KnownLen;
10368 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10369 LLT Ty = MemOps[
I];
10371 if (TySize >
Size) {
10374 assert(
I == MemOps.size() - 1 &&
I != 0);
10375 DstOff -= TySize -
Size;
10385 TLI.isTruncateFree(LargestVT, VT))
10386 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10399 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10402 MIB.buildStore(
Value,
Ptr, *StoreMMO);
10407 MI.eraseFromParent();
10413 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10415 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10417 const auto *MMOIt =
MI.memoperands_begin();
10419 bool IsVolatile =
MemOp->isVolatile();
10425 "inline memcpy with dynamic size is not yet supported");
10426 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10427 if (KnownLen == 0) {
10428 MI.eraseFromParent();
10432 const auto &DstMMO = **
MI.memoperands_begin();
10433 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10434 Align DstAlign = DstMMO.getBaseAlign();
10435 Align SrcAlign = SrcMMO.getBaseAlign();
10437 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10444 Align SrcAlign,
bool IsVolatile) {
10445 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10446 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10447 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10454 Align SrcAlign,
bool IsVolatile) {
10455 auto &MF = *
MI.getParent()->getParent();
10460 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10462 bool DstAlignCanChange =
false;
10464 Align Alignment = std::min(DstAlign, SrcAlign);
10468 DstAlignCanChange =
true;
10474 std::vector<LLT> MemOps;
10476 const auto &DstMMO = **
MI.memoperands_begin();
10477 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10483 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10489 if (DstAlignCanChange) {
10492 Align NewAlign =
DL.getABITypeAlign(IRTy);
10497 if (!
TRI->hasStackRealignment(MF))
10499 NewAlign = std::min(NewAlign, *StackAlign);
10501 if (NewAlign > Alignment) {
10502 Alignment = NewAlign;
10510 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10512 MachineIRBuilder MIB(
MI);
10518 unsigned CurrOffset = 0;
10519 unsigned Size = KnownLen;
10520 for (
auto CopyTy : MemOps) {
10523 if (CopyTy.getSizeInBytes() >
Size)
10524 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10535 if (CurrOffset != 0) {
10536 LLT SrcTy = MRI.getType(Src);
10539 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10541 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10545 if (CurrOffset != 0) {
10546 LLT DstTy = MRI.getType(Dst);
10547 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10549 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10550 CurrOffset += CopyTy.getSizeInBytes();
10551 Size -= CopyTy.getSizeInBytes();
10554 MI.eraseFromParent();
10560 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10562 auto &MF = *
MI.getParent()->getParent();
10567 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10569 bool DstAlignCanChange =
false;
10572 Align Alignment = std::min(DstAlign, SrcAlign);
10574 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10576 DstAlignCanChange =
true;
10578 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10579 std::vector<LLT> MemOps;
10581 const auto &DstMMO = **
MI.memoperands_begin();
10582 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10583 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10584 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10591 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10597 if (DstAlignCanChange) {
10600 Align NewAlign =
DL.getABITypeAlign(IRTy);
10605 if (!
TRI->hasStackRealignment(MF))
10606 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10607 NewAlign = std::min(NewAlign, *StackAlign);
10609 if (NewAlign > Alignment) {
10610 Alignment = NewAlign;
10618 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10620 MachineIRBuilder MIB(
MI);
10624 unsigned CurrOffset = 0;
10625 SmallVector<Register, 16> LoadVals;
10626 for (
auto CopyTy : MemOps) {
10633 if (CurrOffset != 0) {
10634 LLT SrcTy = MRI.getType(Src);
10637 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10639 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10640 CurrOffset += CopyTy.getSizeInBytes();
10644 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10645 LLT CopyTy = MemOps[
I];
10651 if (CurrOffset != 0) {
10652 LLT DstTy = MRI.getType(Dst);
10655 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10657 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10660 MI.eraseFromParent();
10666 const unsigned Opc =
MI.getOpcode();
10669 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10670 Opc == TargetOpcode::G_MEMSET) &&
10671 "Expected memcpy like instruction");
10673 auto MMOIt =
MI.memoperands_begin();
10678 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10680 if (
Opc != TargetOpcode::G_MEMSET) {
10681 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10682 MemOp = *(++MMOIt);
10683 SrcAlign =
MemOp->getBaseAlign();
10688 if (!LenVRegAndVal)
10690 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10692 if (KnownLen == 0) {
10693 MI.eraseFromParent();
10697 if (MaxLen && KnownLen > MaxLen)
10700 bool IsVolatile =
MemOp->isVolatile();
10701 if (
Opc == TargetOpcode::G_MEMCPY) {
10702 auto &MF = *
MI.getParent()->getParent();
10705 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10706 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10709 if (
Opc == TargetOpcode::G_MEMMOVE)
10710 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10711 if (
Opc == TargetOpcode::G_MEMSET)
10712 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.
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.
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.
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 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.
static LLVM_ABI const fltSemantics & IEEEsingle() LLVM_READNONE
static constexpr roundingMode rmNearestTiesToEven
static constexpr roundingMode rmTowardZero
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE
opStatus
IEEE-754R 7: Default exception handling.
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.
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)