43#define DEBUG_TYPE "legalizer"
46using namespace LegalizeActions;
47using namespace MIPatternMatch;
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);
108 : MIRBuilder(Builder), Observer(Observer),
MRI(MF.getRegInfo()),
109 LI(*MF.getSubtarget().getLegalizerInfo()),
110 TLI(*MF.getSubtarget().getTargetLowering()), VT(nullptr) {}
115 : MIRBuilder(
B), Observer(Observer),
MRI(MF.getRegInfo()), LI(LI),
116 TLI(*MF.getSubtarget().getTargetLowering()), VT(VT) {}
125 if (isa<GIntrinsic>(
MI))
128 switch (Step.Action) {
143 return bitcast(
MI, Step.TypeIdx, Step.NewType);
146 return lower(
MI, Step.TypeIdx, Step.NewType);
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);
193 for (
auto PartReg : concat<const Register>(PartRegs, LeftoverRegs))
194 extractGCDType(GCDRegs, GCDTy, PartReg);
195 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
196 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
209void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
212 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
213 appendVectorElts(AllElts, PartRegs[i]);
219 appendVectorElts(AllElts, Leftover);
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();
239 if (SrcTy == GCDTy) {
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)
274 else if (PadStrategy == TargetOpcode::G_ANYEXT)
277 assert(PadStrategy == TargetOpcode::G_SEXT);
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)
321 else if (PadStrategy == TargetOpcode::G_ZEXT)
331 Remerge[
I] = AllPadReg;
335 if (NumSubParts == 1)
336 Remerge[
I] = SubMerge[0];
341 if (AllMergePartsArePadding && !AllPadReg)
342 AllPadReg = Remerge[
I];
345 VRegs = std::move(Remerge);
349void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
356 if (DstTy == LCMTy) {
370 UnmergeDefs[0] = DstReg;
371 for (
unsigned I = 1;
I != NumDefs; ++
I)
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_FLOG10:
476 case TargetOpcode::G_FLOG:
478 case TargetOpcode::G_FLOG2:
480 case TargetOpcode::G_FLDEXP:
482 case TargetOpcode::G_FCEIL:
484 case TargetOpcode::G_FFLOOR:
486 case TargetOpcode::G_FMINNUM:
488 case TargetOpcode::G_FMAXNUM:
490 case TargetOpcode::G_FSQRT:
492 case TargetOpcode::G_FRINT:
494 case TargetOpcode::G_FNEARBYINT:
496 case TargetOpcode::G_INTRINSIC_TRUNC:
498 case TargetOpcode::G_INTRINSIC_ROUND:
500 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
502 case TargetOpcode::G_INTRINSIC_LRINT:
504 case TargetOpcode::G_INTRINSIC_LLRINT:
532 if (CallerAttrs.
hasRetAttr(Attribute::ZExt) ||
544 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
551 if (!VReg.
isVirtual() || VReg != Next->getOperand(1).getReg())
554 Register PReg = Next->getOperand(0).getReg();
562 if (Ret->getNumImplicitOperands() != 1)
565 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
589 Info.OrigRet = Result;
592 (Result.Ty->isVoidTy() ||
598 if (!CLI.lowerCall(MIRBuilder,
Info))
601 if (
MI &&
Info.LoweredTailCall) {
602 assert(
Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
613 "Expected instr following MI to be return or debug inst?");
617 }
while (
MI->getNextNode());
647 Args.push_back({MO.getReg(), OpType, 0});
649 {
MI.getOperand(0).
getReg(), OpType, 0}, Args,
662 LLT DstTy =
MRI.getType(DstSin);
667 unsigned AddrSpace =
DL.getAllocaAddrSpace();
686 if (LibcallResult != LegalizeResult::Legalized)
694 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
695 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
696 MI.eraseFromParent();
708 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
712 LLT OpLLT =
MRI.getType(Reg);
713 Type *OpTy =
nullptr;
718 Args.push_back({Reg, OpTy, 0});
723 RTLIB::Libcall RTLibcall;
724 unsigned Opc =
MI.getOpcode();
727 case TargetOpcode::G_BZERO:
728 RTLibcall = RTLIB::BZERO;
729 Name = TLI.getLibcallName(RTLibcall);
731 case TargetOpcode::G_MEMCPY:
732 RTLibcall = RTLIB::MEMCPY;
733 Name = TLI.getMemcpyName();
734 Args[0].Flags[0].setReturned();
736 case TargetOpcode::G_MEMMOVE:
737 RTLibcall = RTLIB::MEMMOVE;
738 Name = TLI.getLibcallName(RTLibcall);
739 Args[0].Flags[0].setReturned();
741 case TargetOpcode::G_MEMSET:
742 RTLibcall = RTLIB::MEMSET;
743 Name = TLI.getLibcallName(RTLibcall);
744 Args[0].Flags[0].setReturned();
758 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
762 MI.getOperand(
MI.getNumOperands() - 1).
getImm() &&
766 if (!CLI.lowerCall(MIRBuilder,
Info))
769 if (
Info.LoweredTailCall) {
770 assert(
Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
781 "Expected instr following MI to be return or debug inst?");
785 }
while (
MI.getNextNode());
795 unsigned Opc =
MI.getOpcode();
796 auto &AtomicMI = cast<GMemOperation>(
MI);
797 auto &MMO = AtomicMI.getMMO();
798 auto Ordering = MMO.getMergedOrdering();
799 LLT MemType = MMO.getMemoryType();
802 return RTLIB::UNKNOWN_LIBCALL;
804#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
806 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
808 case TargetOpcode::G_ATOMIC_CMPXCHG:
809 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
810 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
811 return getOutlineAtomicHelper(LC, Ordering, MemSize);
813 case TargetOpcode::G_ATOMICRMW_XCHG: {
814 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
815 return getOutlineAtomicHelper(LC, Ordering, MemSize);
817 case TargetOpcode::G_ATOMICRMW_ADD:
818 case TargetOpcode::G_ATOMICRMW_SUB: {
819 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
820 return getOutlineAtomicHelper(LC, Ordering, MemSize);
822 case TargetOpcode::G_ATOMICRMW_AND: {
823 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
824 return getOutlineAtomicHelper(LC, Ordering, MemSize);
826 case TargetOpcode::G_ATOMICRMW_OR: {
827 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
828 return getOutlineAtomicHelper(LC, Ordering, MemSize);
830 case TargetOpcode::G_ATOMICRMW_XOR: {
831 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
832 return getOutlineAtomicHelper(LC, Ordering, MemSize);
835 return RTLIB::UNKNOWN_LIBCALL;
848 unsigned Opc =
MI.getOpcode();
850 case TargetOpcode::G_ATOMIC_CMPXCHG:
851 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
854 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
855 MI.getFirst4RegLLTs();
858 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
859 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
860 NewLLT) =
MI.getFirst5RegLLTs();
870 case TargetOpcode::G_ATOMICRMW_XCHG:
871 case TargetOpcode::G_ATOMICRMW_ADD:
872 case TargetOpcode::G_ATOMICRMW_SUB:
873 case TargetOpcode::G_ATOMICRMW_AND:
874 case TargetOpcode::G_ATOMICRMW_OR:
875 case TargetOpcode::G_ATOMICRMW_XOR: {
876 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
879 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
883 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
898 const char *
Name = TLI.getLibcallName(RTLibcall);
908 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
913 if (!CLI.lowerCall(MIRBuilder,
Info))
925 case TargetOpcode::G_FPEXT:
927 case TargetOpcode::G_FPTRUNC:
929 case TargetOpcode::G_FPTOSI:
931 case TargetOpcode::G_FPTOUI:
933 case TargetOpcode::G_SITOFP:
935 case TargetOpcode::G_UITOFP:
946 if (FromType->isIntegerTy()) {
948 Arg.
Flags[0].setSExt();
950 Arg.
Flags[0].setZExt();
955 {
MI.getOperand(0).
getReg(), ToType, 0}, Arg, LocObserver,
961 RTLIB::Libcall RTLibcall;
962 switch (
MI.getOpcode()) {
963 case TargetOpcode::G_GET_FPENV:
964 RTLibcall = RTLIB::FEGETENV;
966 case TargetOpcode::G_SET_FPENV:
967 case TargetOpcode::G_RESET_FPENV:
968 RTLibcall = RTLIB::FESETENV;
970 case TargetOpcode::G_GET_FPMODE:
971 RTLibcall = RTLIB::FEGETMODE;
973 case TargetOpcode::G_SET_FPMODE:
974 case TargetOpcode::G_RESET_FPMODE:
975 RTLibcall = RTLIB::FESETMODE;
1015 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1022 LocObserver,
nullptr);
1060 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1066 LocObserver,
nullptr);
1072static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1074#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1078 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1080 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1082 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1084 llvm_unreachable("unexpected size"); \
1116 LLT OpLLT =
MRI.getType(
Cmp->getLHSReg());
1119 OpLLT !=
MRI.getType(
Cmp->getRHSReg()))
1126 LLT DstTy =
MRI.getType(DstReg);
1127 const auto Cond =
Cmp->getCond();
1132 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1137 Register Temp =
MRI.createGenericVirtualRegister(TempLLT);
1141 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1154 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1156 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1169 const auto [OeqLibcall, OeqPred] =
1171 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1173 const auto [UnoLibcall, UnoPred] =
1175 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1190 const auto [OeqLibcall, OeqPred] =
1195 const auto [UnoLibcall, UnoPred] =
1200 if (NotOeq && NotUno)
1219 const auto [InversedLibcall, InversedPred] =
1221 if (!BuildLibcall(InversedLibcall,
1247 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1249 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1252 DstOp Dest(
MRI.createGenericVirtualRegister(MemTy));
1266 switch (
MI.getOpcode()) {
1269 case TargetOpcode::G_MUL:
1270 case TargetOpcode::G_SDIV:
1271 case TargetOpcode::G_UDIV:
1272 case TargetOpcode::G_SREM:
1273 case TargetOpcode::G_UREM:
1274 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1275 LLT LLTy =
MRI.getType(
MI.getOperand(0).getReg());
1283 case TargetOpcode::G_FADD:
1284 case TargetOpcode::G_FSUB:
1285 case TargetOpcode::G_FMUL:
1286 case TargetOpcode::G_FDIV:
1287 case TargetOpcode::G_FMA:
1288 case TargetOpcode::G_FPOW:
1289 case TargetOpcode::G_FREM:
1290 case TargetOpcode::G_FCOS:
1291 case TargetOpcode::G_FSIN:
1292 case TargetOpcode::G_FTAN:
1293 case TargetOpcode::G_FACOS:
1294 case TargetOpcode::G_FASIN:
1295 case TargetOpcode::G_FATAN:
1296 case TargetOpcode::G_FATAN2:
1297 case TargetOpcode::G_FCOSH:
1298 case TargetOpcode::G_FSINH:
1299 case TargetOpcode::G_FTANH:
1300 case TargetOpcode::G_FLOG10:
1301 case TargetOpcode::G_FLOG:
1302 case TargetOpcode::G_FLOG2:
1303 case TargetOpcode::G_FEXP:
1304 case TargetOpcode::G_FEXP2:
1305 case TargetOpcode::G_FEXP10:
1306 case TargetOpcode::G_FCEIL:
1307 case TargetOpcode::G_FFLOOR:
1308 case TargetOpcode::G_FMINNUM:
1309 case TargetOpcode::G_FMAXNUM:
1310 case TargetOpcode::G_FSQRT:
1311 case TargetOpcode::G_FRINT:
1312 case TargetOpcode::G_FNEARBYINT:
1313 case TargetOpcode::G_INTRINSIC_TRUNC:
1314 case TargetOpcode::G_INTRINSIC_ROUND:
1315 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1316 LLT LLTy =
MRI.getType(
MI.getOperand(0).getReg());
1320 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1328 case TargetOpcode::G_FSINCOS: {
1329 LLT LLTy =
MRI.getType(
MI.getOperand(0).getReg());
1333 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1338 case TargetOpcode::G_LROUND:
1339 case TargetOpcode::G_LLROUND:
1340 case TargetOpcode::G_INTRINSIC_LRINT:
1341 case TargetOpcode::G_INTRINSIC_LLRINT: {
1342 LLT LLTy =
MRI.getType(
MI.getOperand(1).getReg());
1346 Ctx,
MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1348 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1354 {{
MI.getOperand(1).
getReg(), HLTy, 0}}, LocObserver, &
MI);
1357 MI.eraseFromParent();
1360 case TargetOpcode::G_FPOWI:
1361 case TargetOpcode::G_FLDEXP: {
1362 LLT LLTy =
MRI.getType(
MI.getOperand(0).getReg());
1366 Ctx,
MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1368 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1373 {
MI.getOperand(1).getReg(), HLTy, 0},
1374 {
MI.getOperand(2).getReg(), ITy, 1}};
1375 Args[1].Flags[0].setSExt();
1378 Args, LocObserver, &
MI);
1383 case TargetOpcode::G_FPEXT:
1384 case TargetOpcode::G_FPTRUNC: {
1387 if (!FromTy || !ToTy)
1395 case TargetOpcode::G_FCMP: {
1399 MI.eraseFromParent();
1402 case TargetOpcode::G_FPTOSI:
1403 case TargetOpcode::G_FPTOUI: {
1407 unsigned ToSize =
MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1408 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1416 case TargetOpcode::G_SITOFP:
1417 case TargetOpcode::G_UITOFP: {
1418 unsigned FromSize =
MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1421 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1423 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1426 LocObserver, TLI, IsSigned);
1431 case TargetOpcode::G_ATOMICRMW_XCHG:
1432 case TargetOpcode::G_ATOMICRMW_ADD:
1433 case TargetOpcode::G_ATOMICRMW_SUB:
1434 case TargetOpcode::G_ATOMICRMW_AND:
1435 case TargetOpcode::G_ATOMICRMW_OR:
1436 case TargetOpcode::G_ATOMICRMW_XOR:
1437 case TargetOpcode::G_ATOMIC_CMPXCHG:
1438 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1444 case TargetOpcode::G_BZERO:
1445 case TargetOpcode::G_MEMCPY:
1446 case TargetOpcode::G_MEMMOVE:
1447 case TargetOpcode::G_MEMSET: {
1452 MI.eraseFromParent();
1455 case TargetOpcode::G_GET_FPENV:
1456 case TargetOpcode::G_GET_FPMODE: {
1462 case TargetOpcode::G_SET_FPENV:
1463 case TargetOpcode::G_SET_FPMODE: {
1469 case TargetOpcode::G_RESET_FPENV:
1470 case TargetOpcode::G_RESET_FPMODE: {
1479 MI.eraseFromParent();
1486 uint64_t SizeOp0 =
MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1489 switch (
MI.getOpcode()) {
1492 case TargetOpcode::G_IMPLICIT_DEF: {
1494 LLT DstTy =
MRI.getType(DstReg);
1502 if (SizeOp0 % NarrowSize != 0) {
1503 LLT ImplicitTy = NarrowTy;
1510 MI.eraseFromParent();
1514 int NumParts = SizeOp0 / NarrowSize;
1517 for (
int i = 0; i < NumParts; ++i)
1524 MI.eraseFromParent();
1527 case TargetOpcode::G_CONSTANT: {
1528 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
1529 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1532 int NumParts = TotalSize / NarrowSize;
1535 for (
int I = 0;
I != NumParts; ++
I) {
1536 unsigned Offset =
I * NarrowSize;
1543 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1545 if (LeftoverBits != 0) {
1549 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1553 insertParts(
MI.getOperand(0).getReg(),
1554 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1556 MI.eraseFromParent();
1559 case TargetOpcode::G_SEXT:
1560 case TargetOpcode::G_ZEXT:
1561 case TargetOpcode::G_ANYEXT:
1563 case TargetOpcode::G_TRUNC: {
1567 uint64_t SizeOp1 =
MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1569 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1575 MI.eraseFromParent();
1578 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1579 case TargetOpcode::G_FREEZE: {
1583 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
1590 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1597 MI.eraseFromParent();
1600 case TargetOpcode::G_ADD:
1601 case TargetOpcode::G_SUB:
1602 case TargetOpcode::G_SADDO:
1603 case TargetOpcode::G_SSUBO:
1604 case TargetOpcode::G_SADDE:
1605 case TargetOpcode::G_SSUBE:
1606 case TargetOpcode::G_UADDO:
1607 case TargetOpcode::G_USUBO:
1608 case TargetOpcode::G_UADDE:
1609 case TargetOpcode::G_USUBE:
1611 case TargetOpcode::G_MUL:
1612 case TargetOpcode::G_UMULH:
1614 case TargetOpcode::G_EXTRACT:
1616 case TargetOpcode::G_INSERT:
1618 case TargetOpcode::G_LOAD: {
1619 auto &LoadMI = cast<GLoad>(
MI);
1620 Register DstReg = LoadMI.getDstReg();
1621 LLT DstTy =
MRI.getType(DstReg);
1625 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1626 Register TmpReg =
MRI.createGenericVirtualRegister(NarrowTy);
1629 LoadMI.eraseFromParent();
1635 case TargetOpcode::G_ZEXTLOAD:
1636 case TargetOpcode::G_SEXTLOAD: {
1637 auto &LoadMI = cast<GExtLoad>(
MI);
1638 Register DstReg = LoadMI.getDstReg();
1639 Register PtrReg = LoadMI.getPointerReg();
1641 Register TmpReg =
MRI.createGenericVirtualRegister(NarrowTy);
1642 auto &MMO = LoadMI.getMMO();
1645 if (MemSize == NarrowSize) {
1647 }
else if (MemSize < NarrowSize) {
1649 }
else if (MemSize > NarrowSize) {
1654 if (isa<GZExtLoad>(LoadMI))
1659 LoadMI.eraseFromParent();
1662 case TargetOpcode::G_STORE: {
1663 auto &StoreMI = cast<GStore>(
MI);
1665 Register SrcReg = StoreMI.getValueReg();
1666 LLT SrcTy =
MRI.getType(SrcReg);
1670 int NumParts = SizeOp0 / NarrowSize;
1672 unsigned LeftoverBits = SrcTy.
getSizeInBits() - HandledSize;
1673 if (SrcTy.
isVector() && LeftoverBits != 0)
1676 if (8 * StoreMI.getMemSize().getValue() != SrcTy.
getSizeInBits()) {
1677 Register TmpReg =
MRI.createGenericVirtualRegister(NarrowTy);
1680 StoreMI.eraseFromParent();
1686 case TargetOpcode::G_SELECT:
1688 case TargetOpcode::G_AND:
1689 case TargetOpcode::G_OR:
1690 case TargetOpcode::G_XOR: {
1702 case TargetOpcode::G_SHL:
1703 case TargetOpcode::G_LSHR:
1704 case TargetOpcode::G_ASHR:
1706 case TargetOpcode::G_CTLZ:
1707 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1708 case TargetOpcode::G_CTTZ:
1709 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1710 case TargetOpcode::G_CTPOP:
1712 switch (
MI.getOpcode()) {
1713 case TargetOpcode::G_CTLZ:
1714 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1716 case TargetOpcode::G_CTTZ:
1717 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1719 case TargetOpcode::G_CTPOP:
1729 case TargetOpcode::G_INTTOPTR:
1737 case TargetOpcode::G_PTRTOINT:
1745 case TargetOpcode::G_PHI: {
1748 if (SizeOp0 % NarrowSize != 0)
1751 unsigned NumParts = SizeOp0 / NarrowSize;
1755 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1763 for (
unsigned i = 0; i < NumParts; ++i) {
1764 DstRegs[i] =
MRI.createGenericVirtualRegister(NarrowTy);
1767 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1768 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1773 MI.eraseFromParent();
1776 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1777 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1781 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1787 case TargetOpcode::G_ICMP: {
1801 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1808 LLT ResTy =
MRI.getType(Dst);
1815 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1816 auto LHS = std::get<0>(LHSAndRHS);
1817 auto RHS = std::get<1>(LHSAndRHS);
1825 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1826 auto LHS = std::get<0>(LHSAndRHS);
1827 auto RHS = std::get<1>(LHSAndRHS);
1829 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1830 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1831 TargetOpcode::G_ZEXT);
1838 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1840 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1845 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1849 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1854 CmpOut =
MRI.createGenericVirtualRegister(ResTy);
1864 LHSPartRegs[
I], RHSPartRegs[
I]);
1871 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1875 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1880 CmpOut =
MRI.createGenericVirtualRegister(ResTy);
1885 RHSLeftoverRegs[
I]);
1888 RHSLeftoverRegs[
I]);
1891 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1898 MI.eraseFromParent();
1901 case TargetOpcode::G_FCMP:
1910 case TargetOpcode::G_SEXT_INREG: {
1914 int64_t SizeInBits =
MI.getOperand(2).getImm();
1924 MO1.
setReg(TruncMIB.getReg(0));
1927 Register DstExt =
MRI.createGenericVirtualRegister(NarrowTy);
1939 if (SizeOp0 % NarrowSize != 0)
1941 int NumParts = SizeOp0 / NarrowSize;
1949 for (
int i = 0; i < NumParts; ++i) {
1950 Register SrcReg =
MRI.createGenericVirtualRegister(NarrowTy);
1965 for (
int i = 0; i < NumParts; ++i) {
1968 PartialExtensionReg = DstRegs.
back();
1970 assert(PartialExtensionReg &&
1971 "Expected to visit partial extension before full");
1972 if (FullExtensionReg) {
1979 FullExtensionReg = DstRegs.
back();
1984 TargetOpcode::G_SEXT_INREG, {NarrowTy},
1987 PartialExtensionReg = DstRegs.
back();
1994 MI.eraseFromParent();
1997 case TargetOpcode::G_BSWAP:
1998 case TargetOpcode::G_BITREVERSE: {
1999 if (SizeOp0 % NarrowSize != 0)
2004 unsigned NumParts = SizeOp0 / NarrowSize;
2005 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2008 for (
unsigned i = 0; i < NumParts; ++i) {
2010 {SrcRegs[NumParts - 1 - i]});
2017 MI.eraseFromParent();
2020 case TargetOpcode::G_PTR_ADD:
2021 case TargetOpcode::G_PTRMASK: {
2029 case TargetOpcode::G_FPTOUI:
2030 case TargetOpcode::G_FPTOSI:
2031 case TargetOpcode::G_FPTOUI_SAT:
2032 case TargetOpcode::G_FPTOSI_SAT:
2034 case TargetOpcode::G_FPEXT:
2041 case TargetOpcode::G_FLDEXP:
2042 case TargetOpcode::G_STRICT_FLDEXP:
2044 case TargetOpcode::G_VSCALE: {
2046 LLT Ty =
MRI.getType(Dst);
2055 MI.eraseFromParent();
2062 LLT Ty =
MRI.getType(Val);
2083 unsigned OpIdx,
unsigned ExtOpcode) {
2086 MO.
setReg(ExtB.getReg(0));
2093 MO.
setReg(ExtB.getReg(0));
2097 unsigned OpIdx,
unsigned TruncOpcode) {
2099 Register DstExt =
MRI.createGenericVirtualRegister(WideTy);
2106 unsigned OpIdx,
unsigned ExtOpcode) {
2108 Register DstTrunc =
MRI.createGenericVirtualRegister(NarrowTy);
2119 Register DstExt =
MRI.createGenericVirtualRegister(WideTy);
2137 Register CastDst =
MRI.createGenericVirtualRegister(CastTy);
2144LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2149 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2150 if (DstTy.isVector())
2153 LLT SrcTy =
MRI.getType(Src1Reg);
2154 const int DstSize = DstTy.getSizeInBits();
2157 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2159 unsigned NumOps =
MI.getNumOperands();
2160 unsigned NumSrc =
MI.getNumOperands() - 1;
2161 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2163 if (WideSize >= DstSize) {
2167 for (
unsigned I = 2;
I != NumOps; ++
I) {
2168 const unsigned Offset = (
I - 1) * PartSize;
2175 Register NextResult =
I + 1 == NumOps && WideTy == DstTy ? DstReg :
2176 MRI.createGenericVirtualRegister(WideTy);
2181 ResultReg = NextResult;
2184 if (WideSize > DstSize)
2186 else if (DstTy.isPointer())
2189 MI.eraseFromParent();
2214 const int GCD = std::gcd(SrcSize, WideSize);
2224 if (GCD == SrcSize) {
2228 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2234 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2236 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2240 const int PartsPerGCD = WideSize / GCD;
2244 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2259 MI.eraseFromParent();
2264LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2269 int NumDst =
MI.getNumOperands() - 1;
2270 Register SrcReg =
MI.getOperand(NumDst).getReg();
2271 LLT SrcTy =
MRI.getType(SrcReg);
2275 Register Dst0Reg =
MI.getOperand(0).getReg();
2276 LLT DstTy =
MRI.getType(Dst0Reg);
2285 dbgs() <<
"Not casting non-integral address space integer\n");
2306 for (
int I = 1;
I != NumDst; ++
I) {
2312 MI.eraseFromParent();
2323 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2348 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2353 if (PartsPerRemerge == 1) {
2356 for (
int I = 0;
I != NumUnmerge; ++
I) {
2359 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2360 int Idx =
I * PartsPerUnmerge + J;
2362 MIB.addDef(
MI.getOperand(
Idx).getReg());
2365 MIB.addDef(
MRI.createGenericVirtualRegister(DstTy));
2369 MIB.addUse(Unmerge.getReg(
I));
2373 for (
int J = 0; J != NumUnmerge; ++J)
2374 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2377 for (
int I = 0;
I != NumDst; ++
I) {
2378 for (
int J = 0; J < PartsPerRemerge; ++J) {
2379 const int Idx =
I * PartsPerRemerge + J;
2384 RemergeParts.
clear();
2388 MI.eraseFromParent();
2393LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2395 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2396 unsigned Offset =
MI.getOperand(2).getImm();
2399 if (SrcTy.
isVector() || DstTy.isVector())
2415 if (DstTy.isPointer())
2422 MI.eraseFromParent();
2427 LLT ShiftTy = SrcTy;
2436 MI.eraseFromParent();
2467LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2469 if (TypeIdx != 0 || WideTy.
isVector())
2479LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2483 std::optional<Register> CarryIn;
2484 switch (
MI.getOpcode()) {
2487 case TargetOpcode::G_SADDO:
2488 Opcode = TargetOpcode::G_ADD;
2489 ExtOpcode = TargetOpcode::G_SEXT;
2491 case TargetOpcode::G_SSUBO:
2492 Opcode = TargetOpcode::G_SUB;
2493 ExtOpcode = TargetOpcode::G_SEXT;
2495 case TargetOpcode::G_UADDO:
2496 Opcode = TargetOpcode::G_ADD;
2497 ExtOpcode = TargetOpcode::G_ZEXT;
2499 case TargetOpcode::G_USUBO:
2500 Opcode = TargetOpcode::G_SUB;
2501 ExtOpcode = TargetOpcode::G_ZEXT;
2503 case TargetOpcode::G_SADDE:
2504 Opcode = TargetOpcode::G_UADDE;
2505 ExtOpcode = TargetOpcode::G_SEXT;
2506 CarryIn =
MI.getOperand(4).getReg();
2508 case TargetOpcode::G_SSUBE:
2509 Opcode = TargetOpcode::G_USUBE;
2510 ExtOpcode = TargetOpcode::G_SEXT;
2511 CarryIn =
MI.getOperand(4).getReg();
2513 case TargetOpcode::G_UADDE:
2514 Opcode = TargetOpcode::G_UADDE;
2515 ExtOpcode = TargetOpcode::G_ZEXT;
2516 CarryIn =
MI.getOperand(4).getReg();
2518 case TargetOpcode::G_USUBE:
2519 Opcode = TargetOpcode::G_USUBE;
2520 ExtOpcode = TargetOpcode::G_ZEXT;
2521 CarryIn =
MI.getOperand(4).getReg();
2542 LLT CarryOutTy =
MRI.getType(
MI.getOperand(1).getReg());
2545 {LHSExt, RHSExt, *CarryIn})
2550 LLT OrigTy =
MRI.getType(
MI.getOperand(0).getReg());
2557 MI.eraseFromParent();
2562LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2564 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2565 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2566 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2567 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2568 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2581 unsigned SHLAmount = NewBits -
MRI.getType(DstReg).getScalarSizeInBits();
2593 {ShiftL, ShiftR},
MI.getFlags());
2601 MI.eraseFromParent();
2606LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2615 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2617 LLT SrcTy =
MRI.getType(LHS);
2618 LLT OverflowTy =
MRI.getType(OriginalOverflow);
2625 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2634 WideMulCanOverflow ?
MI.getOpcode() : (
unsigned)TargetOpcode::G_MUL;
2637 if (WideMulCanOverflow)
2639 {LeftOperand, RightOperand});
2660 if (WideMulCanOverflow) {
2668 MI.eraseFromParent();
2674 unsigned Opcode =
MI.getOpcode();
2678 case TargetOpcode::G_ATOMICRMW_XCHG:
2679 case TargetOpcode::G_ATOMICRMW_ADD:
2680 case TargetOpcode::G_ATOMICRMW_SUB:
2681 case TargetOpcode::G_ATOMICRMW_AND:
2682 case TargetOpcode::G_ATOMICRMW_OR:
2683 case TargetOpcode::G_ATOMICRMW_XOR:
2684 case TargetOpcode::G_ATOMICRMW_MIN:
2685 case TargetOpcode::G_ATOMICRMW_MAX:
2686 case TargetOpcode::G_ATOMICRMW_UMIN:
2687 case TargetOpcode::G_ATOMICRMW_UMAX:
2688 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2694 case TargetOpcode::G_ATOMIC_CMPXCHG:
2695 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2702 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2712 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2717 case TargetOpcode::G_EXTRACT:
2718 return widenScalarExtract(
MI, TypeIdx, WideTy);
2719 case TargetOpcode::G_INSERT:
2720 return widenScalarInsert(
MI, TypeIdx, WideTy);
2721 case TargetOpcode::G_MERGE_VALUES:
2722 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2723 case TargetOpcode::G_UNMERGE_VALUES:
2724 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2725 case TargetOpcode::G_SADDO:
2726 case TargetOpcode::G_SSUBO:
2727 case TargetOpcode::G_UADDO:
2728 case TargetOpcode::G_USUBO:
2729 case TargetOpcode::G_SADDE:
2730 case TargetOpcode::G_SSUBE:
2731 case TargetOpcode::G_UADDE:
2732 case TargetOpcode::G_USUBE:
2733 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2734 case TargetOpcode::G_UMULO:
2735 case TargetOpcode::G_SMULO:
2736 return widenScalarMulo(
MI, TypeIdx, WideTy);
2737 case TargetOpcode::G_SADDSAT:
2738 case TargetOpcode::G_SSUBSAT:
2739 case TargetOpcode::G_SSHLSAT:
2740 case TargetOpcode::G_UADDSAT:
2741 case TargetOpcode::G_USUBSAT:
2742 case TargetOpcode::G_USHLSAT:
2743 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2744 case TargetOpcode::G_CTTZ:
2745 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2746 case TargetOpcode::G_CTLZ:
2747 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
2748 case TargetOpcode::G_CTPOP: {
2759 unsigned ExtOpc = Opcode == TargetOpcode::G_CTTZ ||
2760 Opcode == TargetOpcode::G_CTTZ_ZERO_UNDEF
2761 ? TargetOpcode::G_ANYEXT
2762 : TargetOpcode::G_ZEXT;
2764 LLT CurTy =
MRI.getType(SrcReg);
2765 unsigned NewOpc = Opcode;
2766 if (NewOpc == TargetOpcode::G_CTTZ) {
2775 NewOpc = TargetOpcode::G_CTTZ_ZERO_UNDEF;
2780 if (Opcode == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
2792 if (Opcode == TargetOpcode::G_CTLZ) {
2799 MI.eraseFromParent();
2802 case TargetOpcode::G_BSWAP: {
2806 Register ShrReg =
MRI.createGenericVirtualRegister(WideTy);
2807 Register DstExt =
MRI.createGenericVirtualRegister(WideTy);
2808 Register ShiftAmtReg =
MRI.createGenericVirtualRegister(WideTy);
2811 MI.getOperand(0).setReg(DstExt);
2815 LLT Ty =
MRI.getType(DstReg);
2824 case TargetOpcode::G_BITREVERSE: {
2828 LLT Ty =
MRI.getType(DstReg);
2831 Register DstExt =
MRI.createGenericVirtualRegister(WideTy);
2833 MI.getOperand(0).setReg(DstExt);
2842 case TargetOpcode::G_FREEZE:
2843 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2850 case TargetOpcode::G_ABS:
2857 case TargetOpcode::G_ADD:
2858 case TargetOpcode::G_AND:
2859 case TargetOpcode::G_MUL:
2860 case TargetOpcode::G_OR:
2861 case TargetOpcode::G_XOR:
2862 case TargetOpcode::G_SUB:
2863 case TargetOpcode::G_SHUFFLE_VECTOR:
2874 case TargetOpcode::G_SBFX:
2875 case TargetOpcode::G_UBFX:
2889 case TargetOpcode::G_SHL:
2905 case TargetOpcode::G_ROTR:
2906 case TargetOpcode::G_ROTL:
2915 case TargetOpcode::G_SDIV:
2916 case TargetOpcode::G_SREM:
2917 case TargetOpcode::G_SMIN:
2918 case TargetOpcode::G_SMAX:
2926 case TargetOpcode::G_SDIVREM:
2935 case TargetOpcode::G_ASHR:
2936 case TargetOpcode::G_LSHR:
2940 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
2941 : TargetOpcode::G_ZEXT;
2954 case TargetOpcode::G_UDIV:
2955 case TargetOpcode::G_UREM:
2962 case TargetOpcode::G_UDIVREM:
2970 case TargetOpcode::G_UMIN:
2971 case TargetOpcode::G_UMAX: {
2972 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
2978 ? TargetOpcode::G_SEXT
2979 : TargetOpcode::G_ZEXT;
2989 case TargetOpcode::G_SELECT:
2999 bool IsVec =
MRI.getType(
MI.getOperand(1).getReg()).isVector();
3006 case TargetOpcode::G_FPTOSI:
3007 case TargetOpcode::G_FPTOUI:
3008 case TargetOpcode::G_INTRINSIC_LRINT:
3009 case TargetOpcode::G_INTRINSIC_LLRINT:
3010 case TargetOpcode::G_IS_FPCLASS:
3020 case TargetOpcode::G_SITOFP:
3030 case TargetOpcode::G_UITOFP:
3040 case TargetOpcode::G_FPTOSI_SAT:
3041 case TargetOpcode::G_FPTOUI_SAT:
3046 LLT Ty =
MRI.getType(OldDst);
3047 Register ExtReg =
MRI.createGenericVirtualRegister(WideTy);
3049 MI.getOperand(0).setReg(ExtReg);
3053 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3081 case TargetOpcode::G_LOAD:
3082 case TargetOpcode::G_SEXTLOAD:
3083 case TargetOpcode::G_ZEXTLOAD:
3089 case TargetOpcode::G_STORE: {
3093 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
3103 MI.setMemRefs(MF, {NewMMO});
3111 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3117 case TargetOpcode::G_CONSTANT: {
3121 MRI.getType(
MI.getOperand(0).getReg()));
3122 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3123 ExtOpc == TargetOpcode::G_ANYEXT) &&
3126 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3130 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3136 case TargetOpcode::G_FCONSTANT: {
3144 MI.eraseFromParent();
3147 case TargetOpcode::G_IMPLICIT_DEF: {
3153 case TargetOpcode::G_BRCOND:
3159 case TargetOpcode::G_FCMP:
3170 case TargetOpcode::G_ICMP:
3175 LLT SrcTy =
MRI.getType(
MI.getOperand(2).getReg());
3180 unsigned ExtOpcode =
3184 ? TargetOpcode::G_SEXT
3185 : TargetOpcode::G_ZEXT;
3192 case TargetOpcode::G_PTR_ADD:
3193 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3199 case TargetOpcode::G_PHI: {
3200 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3203 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3215 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3218 LLT VecTy =
MRI.getType(VecReg);
3223 TargetOpcode::G_ANYEXT);
3238 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3254 LLT VecTy =
MRI.getType(VecReg);
3274 case TargetOpcode::G_FADD:
3275 case TargetOpcode::G_FMUL:
3276 case TargetOpcode::G_FSUB:
3277 case TargetOpcode::G_FMA:
3278 case TargetOpcode::G_FMAD:
3279 case TargetOpcode::G_FNEG:
3280 case TargetOpcode::G_FABS:
3281 case TargetOpcode::G_FCANONICALIZE:
3282 case TargetOpcode::G_FMINNUM:
3283 case TargetOpcode::G_FMAXNUM:
3284 case TargetOpcode::G_FMINNUM_IEEE:
3285 case TargetOpcode::G_FMAXNUM_IEEE:
3286 case TargetOpcode::G_FMINIMUM:
3287 case TargetOpcode::G_FMAXIMUM:
3288 case TargetOpcode::G_FMINIMUMNUM:
3289 case TargetOpcode::G_FMAXIMUMNUM:
3290 case TargetOpcode::G_FDIV:
3291 case TargetOpcode::G_FREM:
3292 case TargetOpcode::G_FCEIL:
3293 case TargetOpcode::G_FFLOOR:
3294 case TargetOpcode::G_FCOS:
3295 case TargetOpcode::G_FSIN:
3296 case TargetOpcode::G_FTAN:
3297 case TargetOpcode::G_FACOS:
3298 case TargetOpcode::G_FASIN:
3299 case TargetOpcode::G_FATAN:
3300 case TargetOpcode::G_FATAN2:
3301 case TargetOpcode::G_FCOSH:
3302 case TargetOpcode::G_FSINH:
3303 case TargetOpcode::G_FTANH:
3304 case TargetOpcode::G_FLOG10:
3305 case TargetOpcode::G_FLOG:
3306 case TargetOpcode::G_FLOG2:
3307 case TargetOpcode::G_FRINT:
3308 case TargetOpcode::G_FNEARBYINT:
3309 case TargetOpcode::G_FSQRT:
3310 case TargetOpcode::G_FEXP:
3311 case TargetOpcode::G_FEXP2:
3312 case TargetOpcode::G_FEXP10:
3313 case TargetOpcode::G_FPOW:
3314 case TargetOpcode::G_INTRINSIC_TRUNC:
3315 case TargetOpcode::G_INTRINSIC_ROUND:
3316 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3320 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3326 case TargetOpcode::G_FPOWI:
3327 case TargetOpcode::G_FLDEXP:
3328 case TargetOpcode::G_STRICT_FLDEXP: {
3330 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3351 case TargetOpcode::G_FFREXP: {
3364 case TargetOpcode::G_INTTOPTR:
3372 case TargetOpcode::G_PTRTOINT:
3380 case TargetOpcode::G_BUILD_VECTOR: {
3384 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3398 case TargetOpcode::G_SEXT_INREG:
3407 case TargetOpcode::G_PTRMASK: {
3415 case TargetOpcode::G_VECREDUCE_ADD: {
3424 case TargetOpcode::G_VECREDUCE_FADD:
3425 case TargetOpcode::G_VECREDUCE_FMUL:
3426 case TargetOpcode::G_VECREDUCE_FMIN:
3427 case TargetOpcode::G_VECREDUCE_FMAX:
3428 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3429 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3434 LLT VecTy =
MRI.getType(VecReg);
3443 case TargetOpcode::G_VSCALE: {
3450 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3455 case TargetOpcode::G_SPLAT_VECTOR: {
3464 case TargetOpcode::G_INSERT_SUBVECTOR: {
3472 LLT SubVecTy =
MRI.getType(SubVec);
3487 MI.eraseFromParent();
3496 auto Unmerge =
B.buildUnmerge(Ty, Src);
3497 for (
int I = 0, E = Unmerge->getNumOperands() - 1;
I != E; ++
I)
3506 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3508 LLT DstLLT =
MRI.getType(DstReg);
3529 MI.eraseFromParent();
3540 MI.eraseFromParent();
3547 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3552 if (DstTy.isVector()) {
3553 int NumDstElt = DstTy.getNumElements();
3557 LLT DstCastTy = DstEltTy;
3558 LLT SrcPartTy = SrcEltTy;
3562 if (NumSrcElt < NumDstElt) {
3572 SrcPartTy = SrcEltTy;
3573 }
else if (NumSrcElt > NumDstElt) {
3584 DstCastTy = DstEltTy;
3594 MI.eraseFromParent();
3598 if (DstTy.isVector()) {
3602 MI.eraseFromParent();
3618 unsigned NewEltSize,
3619 unsigned OldEltSize) {
3620 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3621 LLT IdxTy =
B.getMRI()->getType(
Idx);
3624 auto OffsetMask =
B.buildConstant(
3626 auto OffsetIdx =
B.buildAnd(IdxTy,
Idx, OffsetMask);
3627 return B.buildShl(IdxTy, OffsetIdx,
3628 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3643 auto [Dst, DstTy, SrcVec, SrcVecTy,
Idx, IdxTy] =
MI.getFirst3RegLLTs();
3647 unsigned OldNumElts = SrcVecTy.getNumElements();
3654 if (NewNumElts > OldNumElts) {
3665 if (NewNumElts % OldNumElts != 0)
3669 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3678 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3682 NewOps[
I] = Elt.getReg(0);
3687 MI.eraseFromParent();
3691 if (NewNumElts < OldNumElts) {
3692 if (NewEltSize % OldEltSize != 0)
3714 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3733 MI.eraseFromParent();
3747 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3748 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3749 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3750 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3753 auto EltMask =
B.buildConstant(
3757 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3758 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3761 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3765 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3779 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy,
Idx, IdxTy] =
3780 MI.getFirst4RegLLTs();
3792 if (NewNumElts < OldNumElts) {
3793 if (NewEltSize % OldEltSize != 0)
3802 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3822 CastTy, CastVec, InsertedElt, ScaledIdx).
getReg(0);
3826 MI.eraseFromParent();
3850 auto ConcatMI = dyn_cast<GConcatVectors>(&
MI);
3856 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3860 if (!LI.
isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3861 return UnableToLegalize;
3866 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3868 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3877 MI.eraseFromParent();
3894 auto ShuffleMI = cast<GShuffleVector>(&
MI);
3895 LLT DstTy =
MRI.getType(ShuffleMI->getReg(0));
3896 LLT SrcTy =
MRI.getType(ShuffleMI->getReg(1));
3912 MI.eraseFromParent();
3928 auto ES = cast<GExtractSubvector>(&
MI);
3942 LLT DstTy =
MRI.getType(Dst);
3943 LLT SrcTy =
MRI.getType(Src);
3949 if (DstTy == CastTy)
3957 if (CastEltSize < DstEltSize)
3960 auto AdjustAmt = CastEltSize / DstEltSize;
3961 if (
Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
3962 SrcTyMinElts % AdjustAmt != 0)
3991 auto ES = cast<GInsertSubvector>(&
MI);
4006 LLT DstTy =
MRI.getType(Dst);
4007 LLT BigVecTy =
MRI.getType(BigVec);
4008 LLT SubVecTy =
MRI.getType(SubVec);
4010 if (DstTy == CastTy)
4025 if (CastEltSize < DstEltSize)
4028 auto AdjustAmt = CastEltSize / DstEltSize;
4029 if (
Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4030 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4050 LLT DstTy =
MRI.getType(DstReg);
4058 if (MemSizeInBits != MemStoreSizeInBits) {
4075 LoadReg =
MRI.createGenericVirtualRegister(WideMemTy);
4078 if (isa<GSExtLoad>(LoadMI)) {
4081 }
else if (isa<GZExtLoad>(LoadMI) || WideMemTy == LoadTy) {
4090 if (DstTy != LoadTy)
4116 uint64_t LargeSplitSize, SmallSplitSize;
4121 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4131 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4142 if (Alignment.
value() * 8 > MemSizeInBits &&
4164 LLT PtrTy =
MRI.getType(PtrReg);
4171 LargeSplitSize / 8);
4172 Register PtrAddReg =
MRI.createGenericVirtualRegister(PtrTy);
4175 SmallPtr, *SmallMMO);
4180 if (AnyExtTy == DstTy)
4207 LLT SrcTy =
MRI.getType(SrcReg);
4215 if (StoreWidth != StoreSizeInBits && !SrcTy.
isVector()) {
4246 uint64_t LargeSplitSize, SmallSplitSize;
4249 LargeSplitSize = llvm::bit_floor<uint64_t>(MemTy.
getSizeInBits());
4256 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4277 LLT PtrTy =
MRI.getType(PtrReg);
4296 LLT SrcTy =
MRI.getType(SrcReg);
4338 switch (
MI.getOpcode()) {
4339 case TargetOpcode::G_LOAD: {
4357 case TargetOpcode::G_STORE: {
4373 case TargetOpcode::G_SELECT: {
4377 if (
MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4379 dbgs() <<
"bitcast action not implemented for vector select\n");
4390 case TargetOpcode::G_AND:
4391 case TargetOpcode::G_OR:
4392 case TargetOpcode::G_XOR: {
4400 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4402 case TargetOpcode::G_INSERT_VECTOR_ELT:
4404 case TargetOpcode::G_CONCAT_VECTORS:
4406 case TargetOpcode::G_SHUFFLE_VECTOR:
4408 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4410 case TargetOpcode::G_INSERT_SUBVECTOR:
4418void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4426 using namespace TargetOpcode;
4428 switch(
MI.getOpcode()) {
4431 case TargetOpcode::G_FCONSTANT:
4433 case TargetOpcode::G_BITCAST:
4435 case TargetOpcode::G_SREM:
4436 case TargetOpcode::G_UREM: {
4437 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
4440 {MI.getOperand(1), MI.getOperand(2)});
4444 MI.eraseFromParent();
4447 case TargetOpcode::G_SADDO:
4448 case TargetOpcode::G_SSUBO:
4450 case TargetOpcode::G_UMULH:
4451 case TargetOpcode::G_SMULH:
4453 case TargetOpcode::G_SMULO:
4454 case TargetOpcode::G_UMULO: {
4457 auto [Res, Overflow,
LHS,
RHS] =
MI.getFirst4Regs();
4458 LLT Ty =
MRI.getType(Res);
4460 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4461 ? TargetOpcode::G_SMULH
4462 : TargetOpcode::G_UMULH;
4466 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4467 MI.removeOperand(1);
4478 if (Opcode == TargetOpcode::G_SMULH) {
4487 case TargetOpcode::G_FNEG: {
4488 auto [Res, SubByReg] =
MI.getFirst2Regs();
4489 LLT Ty =
MRI.getType(Res);
4494 MI.eraseFromParent();
4497 case TargetOpcode::G_FSUB:
4498 case TargetOpcode::G_STRICT_FSUB: {
4499 auto [Res,
LHS,
RHS] =
MI.getFirst3Regs();
4500 LLT Ty =
MRI.getType(Res);
4505 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4510 MI.eraseFromParent();
4513 case TargetOpcode::G_FMAD:
4515 case TargetOpcode::G_FFLOOR:
4517 case TargetOpcode::G_LROUND:
4518 case TargetOpcode::G_LLROUND: {
4521 LLT SrcTy =
MRI.getType(SrcReg);
4525 MI.eraseFromParent();
4528 case TargetOpcode::G_INTRINSIC_ROUND:
4530 case TargetOpcode::G_FRINT: {
4533 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4536 case TargetOpcode::G_INTRINSIC_LRINT:
4537 case TargetOpcode::G_INTRINSIC_LLRINT: {
4540 LLT SrcTy =
MRI.getType(SrcReg);
4544 MI.eraseFromParent();
4547 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4548 auto [OldValRes, SuccessRes,
Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4549 Register NewOldValRes =
MRI.cloneVirtualRegister(OldValRes);
4551 **
MI.memoperands_begin());
4554 MI.eraseFromParent();
4557 case TargetOpcode::G_LOAD:
4558 case TargetOpcode::G_SEXTLOAD:
4559 case TargetOpcode::G_ZEXTLOAD:
4561 case TargetOpcode::G_STORE:
4563 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4564 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4565 case TargetOpcode::G_CTLZ:
4566 case TargetOpcode::G_CTTZ:
4567 case TargetOpcode::G_CTPOP:
4570 auto [Res, CarryOut,
LHS,
RHS] =
MI.getFirst4Regs();
4579 MI.eraseFromParent();
4583 auto [Res, CarryOut,
LHS,
RHS, CarryIn] =
MI.getFirst5Regs();
4584 const LLT CondTy =
MRI.getType(CarryOut);
4585 const LLT Ty =
MRI.getType(Res);
4609 MI.eraseFromParent();
4613 auto [Res, BorrowOut,
LHS,
RHS] =
MI.getFirst4Regs();
4618 MI.eraseFromParent();
4622 auto [Res, BorrowOut,
LHS,
RHS, BorrowIn] =
MI.getFirst5Regs();
4623 const LLT CondTy =
MRI.getType(BorrowOut);
4624 const LLT Ty =
MRI.getType(Res);
4644 MI.eraseFromParent();
4677 case G_MERGE_VALUES:
4679 case G_UNMERGE_VALUES:
4681 case TargetOpcode::G_SEXT_INREG: {
4682 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4683 int64_t SizeInBits =
MI.getOperand(2).getImm();
4685 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4686 LLT DstTy =
MRI.getType(DstReg);
4687 Register TmpRes =
MRI.createGenericVirtualRegister(DstTy);
4692 MI.eraseFromParent();
4695 case G_EXTRACT_VECTOR_ELT:
4696 case G_INSERT_VECTOR_ELT:
4698 case G_SHUFFLE_VECTOR:
4700 case G_VECTOR_COMPRESS:
4702 case G_DYN_STACKALLOC:
4706 case G_STACKRESTORE:
4716 case G_READ_REGISTER:
4717 case G_WRITE_REGISTER:
4724 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
4731 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
4764 case G_MEMCPY_INLINE:
4765 return lowerMemcpyInline(
MI);
4796 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4806 Align StackTypeAlign =
4819 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4831 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4834 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4845 "Converting bits to bytes lost precision");
4851 unsigned AS =
MRI.getType(VecPtr).getAddressSpace();
4852 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4853 LLT IdxTy =
MRI.getType(Index).changeElementSize(IndexSizeInBits);
4854 if (IdxTy !=
MRI.getType(Index))
4860 LLT PtrTy =
MRI.getType(VecPtr);
4869 std::initializer_list<unsigned> NonVecOpIndices) {
4870 if (
MI.getNumMemOperands() != 0)
4873 LLT VecTy =
MRI.getType(
MI.getReg(0));
4911 int NumParts, NumLeftover;
4912 std::tie(NumParts, NumLeftover) =
4915 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
4916 for (
int i = 0; i < NumParts; ++i) {
4921 assert(NumLeftover == 1 &&
"expected exactly one leftover");
4930 for (
unsigned i = 0; i <
N; ++i) {
4933 else if (
Op.isImm())
4935 else if (
Op.isPredicate())
4957 std::initializer_list<unsigned> NonVecOpIndices) {
4959 "Non-compatible opcode or not specified non-vector operands");
4960 unsigned OrigNumElts =
MRI.getType(
MI.getReg(0)).getNumElements();
4962 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
4963 unsigned NumDefs =
MI.getNumDefs();
4971 for (
unsigned i = 0; i < NumDefs; ++i) {
4980 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
4981 ++UseIdx, ++UseNo) {
4984 MI.getOperand(UseIdx));
4993 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
4997 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
4999 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5000 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5003 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5004 Uses.push_back(InputOpsPieces[InputNo][i]);
5007 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5008 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5013 for (
unsigned i = 0; i < NumDefs; ++i)
5014 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5016 for (
unsigned i = 0; i < NumDefs; ++i)
5020 MI.eraseFromParent();
5027 unsigned OrigNumElts =
MRI.getType(
MI.getReg(0)).getNumElements();
5029 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5030 unsigned NumDefs =
MI.getNumDefs();
5039 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5040 UseIdx += 2, ++UseNo) {
5048 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5050 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5053 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(
MRI)));
5056 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5057 Phi.addUse(InputOpsPieces[j][i]);
5058 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5068 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5073 MI.eraseFromParent();
5081 const int NumDst =
MI.getNumOperands() - 1;
5082 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5083 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
5084 LLT SrcTy =
MRI.getType(SrcReg);
5086 if (TypeIdx != 1 || NarrowTy == DstTy)
5112 const int PartsPerUnmerge = NumDst / NumUnmerge;
5114 for (
int I = 0;
I != NumUnmerge; ++
I) {
5117 for (
int J = 0; J != PartsPerUnmerge; ++J)
5118 MIB.
addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5119 MIB.
addUse(Unmerge.getReg(
I));
5122 MI.eraseFromParent();
5129 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5133 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5135 if (NarrowTy == SrcTy)
5145 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5158 LLT EltTy =
MRI.getType(
MI.getOperand(1).getReg()).getScalarType();
5159 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5161 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5167 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5168 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5169 ++i,
Offset += NumNarrowTyElts) {
5176 MI.eraseFromParent();
5180 assert(TypeIdx == 0 &&
"Bad type index");
5196 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5199 for (
unsigned i = 0; i < NumParts; ++i) {
5201 for (
unsigned j = 0; j < NumElts; ++j)
5202 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5208 MI.eraseFromParent();
5216 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5218 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5220 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5222 InsertVal =
MI.getOperand(2).getReg();
5225 LLT VecTy =
MRI.getType(SrcVec);
5231 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5235 MI.eraseFromParent();
5244 SplitPieces[IdxVal] = InsertVal;
5251 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5254 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5255 TargetOpcode::G_ANYEXT);
5260 int64_t PartIdx = IdxVal / NewNumElts;
5265 LLT PartTy =
MRI.getType(VecParts[PartIdx]);
5269 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5270 VecParts[PartIdx] = InsertPart.getReg(0);
5274 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5280 MI.eraseFromParent();
5300 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5309 bool IsLoad = isa<GLoad>(LdStMI);
5312 LLT ValTy =
MRI.getType(ValReg);
5321 int NumLeftover = -1;
5327 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5329 NumParts = NarrowRegs.
size();
5330 NumLeftover = NarrowLeftoverRegs.
size();
5337 LLT PtrTy =
MRI.getType(AddrReg);
5347 auto MMO = LdStMI.
getMMO();
5349 unsigned NumParts,
unsigned Offset) ->
unsigned {
5352 for (
unsigned Idx = 0, E = NumParts;
Idx != E &&
Offset < TotalSize;
5354 unsigned ByteOffset =
Offset / 8;
5364 Register Dst =
MRI.createGenericVirtualRegister(PartTy);
5365 ValRegs.push_back(Dst);
5377 unsigned HandledOffset =
5378 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5382 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5385 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5386 LeftoverTy, NarrowLeftoverRegs);
5396 using namespace TargetOpcode;
5400 switch (
MI.getOpcode()) {
5401 case G_IMPLICIT_DEF:
5417 case G_FCANONICALIZE:
5434 case G_INTRINSIC_LRINT:
5435 case G_INTRINSIC_LLRINT:
5436 case G_INTRINSIC_ROUND:
5437 case G_INTRINSIC_ROUNDEVEN:
5440 case G_INTRINSIC_TRUNC:
5467 case G_FMINNUM_IEEE:
5468 case G_FMAXNUM_IEEE:
5490 case G_CTLZ_ZERO_UNDEF:
5492 case G_CTTZ_ZERO_UNDEF:
5508 case G_ADDRSPACE_CAST:
5521 case G_STRICT_FLDEXP:
5530 if (
MRI.getType(
MI.getOperand(1).getReg()).isVector())
5535 case G_UNMERGE_VALUES:
5537 case G_BUILD_VECTOR:
5538 assert(TypeIdx == 0 &&
"not a vector type index");
5540 case G_CONCAT_VECTORS:
5544 case G_EXTRACT_VECTOR_ELT:
5545 case G_INSERT_VECTOR_ELT:
5554 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5555 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5557 case G_SHUFFLE_VECTOR:
5563 case G_INTRINSIC_FPTRUNC_ROUND:
5573 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5574 "Not a bitcast operation");
5579 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5581 unsigned NewElemCount =
5584 if (NewElemCount == 1) {
5593 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5603 MI.eraseFromParent();
5609 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5613 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5614 MI.getFirst3RegLLTs();
5617 if (DstTy != Src1Ty)
5619 if (DstTy != Src2Ty)
5634 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5650 unsigned InputUsed[2] = {-1U, -1U};
5651 unsigned FirstMaskIdx =
High * NewElts;
5652 bool UseBuildVector =
false;
5653 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5655 int Idx = Mask[FirstMaskIdx + MaskOffset];
5660 if (Input >= std::size(Inputs)) {
5667 Idx -= Input * NewElts;
5671 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5672 if (InputUsed[OpNo] == Input) {
5675 }
else if (InputUsed[OpNo] == -1U) {
5677 InputUsed[OpNo] = Input;
5682 if (OpNo >= std::size(InputUsed)) {
5685 UseBuildVector =
true;
5693 if (UseBuildVector) {
5698 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5700 int Idx = Mask[FirstMaskIdx + MaskOffset];
5705 if (Input >= std::size(Inputs)) {
5712 Idx -= Input * NewElts;
5716 .buildExtractVectorElement(
5717 EltTy, Inputs[Input],
5724 }
else if (InputUsed[0] == -1U) {
5728 Register Op0 = Inputs[InputUsed[0]];
5732 : Inputs[InputUsed[1]];
5741 MI.eraseFromParent();
5747 auto &RdxMI = cast<GVecReduce>(
MI);
5754 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5760 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5763 const unsigned NumParts =
5769 if (DstTy != NarrowTy)
5775 unsigned NumPartsLeft = NumParts;
5776 while (NumPartsLeft > 1) {
5777 for (
unsigned Idx = 0;
Idx < NumPartsLeft - 1;
Idx += 2) {
5780 .buildInstr(ScalarOpc, {NarrowTy},
5781 {SplitSrcs[
Idx], SplitSrcs[
Idx + 1]})
5784 SplitSrcs = PartialResults;
5785 PartialResults.
clear();
5786 NumPartsLeft = SplitSrcs.
size();
5790 MI.eraseFromParent();
5795 for (
unsigned Idx = 1;
Idx < NumParts; ++
Idx)
5799 MI.eraseFromParent();
5803 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5813 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5816 Register Acc = PartialReductions[0];
5817 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5818 if (Part == NumParts - 1) {
5820 {Acc, PartialReductions[Part]});
5823 .
buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5827 MI.eraseFromParent();
5833 unsigned int TypeIdx,
5835 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5836 MI.getFirst3RegLLTs();
5837 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5841 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5842 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5843 "Unexpected vecreduce opcode");
5844 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5845 ? TargetOpcode::G_FADD
5846 : TargetOpcode::G_FMUL;
5852 for (
unsigned i = 0; i < NumParts; i++)
5857 MI.eraseFromParent();
5864 unsigned ScalarOpc) {
5872 while (SplitSrcs.
size() > 1) {
5874 for (
unsigned Idx = 0;
Idx < SplitSrcs.
size()-1;
Idx += 2) {
5882 SplitSrcs = std::move(PartialRdxs);
5886 MI.getOperand(1).setReg(SplitSrcs[0]);
5893 const LLT HalfTy,
const LLT AmtTy) {
5895 Register InL =
MRI.createGenericVirtualRegister(HalfTy);
5896 Register InH =
MRI.createGenericVirtualRegister(HalfTy);
5901 MI.eraseFromParent();
5907 unsigned VTBits = 2 * NVTBits;
5910 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
5911 if (Amt.
ugt(VTBits)) {
5913 }
else if (Amt.
ugt(NVTBits)) {
5917 }
else if (Amt == NVTBits) {
5928 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
5929 if (Amt.
ugt(VTBits)) {
5931 }
else if (Amt.
ugt(NVTBits)) {
5935 }
else if (Amt == NVTBits) {
5949 if (Amt.
ugt(VTBits)) {
5952 }
else if (Amt.
ugt(NVTBits)) {
5957 }
else if (Amt == NVTBits) {
5974 MI.eraseFromParent();
5991 LLT DstTy =
MRI.getType(DstReg);
5996 LLT ShiftAmtTy =
MRI.getType(Amt);
5998 if (DstEltSize % 2 != 0)
6004 const unsigned NewBitSize = DstEltSize / 2;
6018 Register InL =
MRI.createGenericVirtualRegister(HalfTy);
6019 Register InH =
MRI.createGenericVirtualRegister(HalfTy);
6030 switch (
MI.getOpcode()) {
6031 case TargetOpcode::G_SHL: {
6047 ResultRegs[0] =
Lo.getReg(0);
6048 ResultRegs[1] =
Hi.getReg(0);
6051 case TargetOpcode::G_LSHR:
6052 case TargetOpcode::G_ASHR: {
6062 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6076 ResultRegs[0] =
Lo.getReg(0);
6077 ResultRegs[1] =
Hi.getReg(0);
6085 MI.eraseFromParent();
6092 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6095 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6110 assert(Ty.
isScalar() &&
"Expected scalar type to make neutral element for");
6115 "getNeutralElementForVecReduce called with invalid opcode!");
6116 case TargetOpcode::G_VECREDUCE_ADD:
6117 case TargetOpcode::G_VECREDUCE_OR:
6118 case TargetOpcode::G_VECREDUCE_XOR:
6119 case TargetOpcode::G_VECREDUCE_UMAX:
6121 case TargetOpcode::G_VECREDUCE_MUL:
6123 case TargetOpcode::G_VECREDUCE_AND:
6124 case TargetOpcode::G_VECREDUCE_UMIN:
6127 case TargetOpcode::G_VECREDUCE_SMAX:
6130 case TargetOpcode::G_VECREDUCE_SMIN:
6133 case TargetOpcode::G_VECREDUCE_FADD:
6135 case TargetOpcode::G_VECREDUCE_FMUL:
6137 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6138 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6139 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6140 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6148 unsigned Opc =
MI.getOpcode();
6150 case TargetOpcode::G_IMPLICIT_DEF:
6151 case TargetOpcode::G_LOAD: {
6159 case TargetOpcode::G_STORE:
6166 case TargetOpcode::G_AND:
6167 case TargetOpcode::G_OR:
6168 case TargetOpcode::G_XOR:
6169 case TargetOpcode::G_ADD:
6170 case TargetOpcode::G_SUB:
6171 case TargetOpcode::G_MUL:
6172 case TargetOpcode::G_FADD:
6173 case TargetOpcode::G_FSUB:
6174 case TargetOpcode::G_FMUL:
6175 case TargetOpcode::G_FDIV:
6176 case TargetOpcode::G_FCOPYSIGN:
6177 case TargetOpcode::G_UADDSAT:
6178 case TargetOpcode::G_USUBSAT:
6179 case TargetOpcode::G_SADDSAT:
6180 case TargetOpcode::G_SSUBSAT:
6181 case TargetOpcode::G_SMIN:
6182 case TargetOpcode::G_SMAX:
6183 case TargetOpcode::G_UMIN:
6184 case TargetOpcode::G_UMAX:
6185 case TargetOpcode::G_FMINNUM:
6186 case TargetOpcode::G_FMAXNUM:
6187 case TargetOpcode::G_FMINNUM_IEEE:
6188 case TargetOpcode::G_FMAXNUM_IEEE:
6189 case TargetOpcode::G_FMINIMUM:
6190 case TargetOpcode::G_FMAXIMUM:
6191 case TargetOpcode::G_FMINIMUMNUM:
6192 case TargetOpcode::G_FMAXIMUMNUM:
6193 case TargetOpcode::G_STRICT_FADD:
6194 case TargetOpcode::G_STRICT_FSUB:
6195 case TargetOpcode::G_STRICT_FMUL:
6196 case TargetOpcode::G_SHL:
6197 case TargetOpcode::G_ASHR:
6198 case TargetOpcode::G_LSHR: {
6206 case TargetOpcode::G_FMA:
6207 case TargetOpcode::G_STRICT_FMA:
6208 case TargetOpcode::G_FSHR:
6209 case TargetOpcode::G_FSHL: {
6218 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6219 case TargetOpcode::G_EXTRACT:
6226 case TargetOpcode::G_INSERT:
6227 case TargetOpcode::G_INSERT_VECTOR_ELT:
6228 case TargetOpcode::G_FREEZE:
6229 case TargetOpcode::G_FNEG:
6230 case TargetOpcode::G_FABS:
6231 case TargetOpcode::G_FSQRT:
6232 case TargetOpcode::G_FCEIL:
6233 case TargetOpcode::G_FFLOOR:
6234 case TargetOpcode::G_FNEARBYINT:
6235 case TargetOpcode::G_FRINT:
6236 case TargetOpcode::G_INTRINSIC_ROUND:
6237 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6238 case TargetOpcode::G_INTRINSIC_TRUNC:
6239 case TargetOpcode::G_BITREVERSE:
6240 case TargetOpcode::G_BSWAP:
6241 case TargetOpcode::G_FCANONICALIZE:
6242 case TargetOpcode::G_SEXT_INREG:
6243 case TargetOpcode::G_ABS:
6244 case TargetOpcode::G_CTLZ:
6245 case TargetOpcode::G_CTPOP:
6253 case TargetOpcode::G_SELECT: {
6254 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6256 if (!CondTy.isScalar() ||
6264 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6269 if (CondTy.isVector())
6279 case TargetOpcode::G_UNMERGE_VALUES:
6281 case TargetOpcode::G_PHI:
6283 case TargetOpcode::G_SHUFFLE_VECTOR:
6285 case TargetOpcode::G_BUILD_VECTOR: {
6287 for (
auto Op :
MI.uses()) {
6297 MI.eraseFromParent();
6300 case TargetOpcode::G_SEXT:
6301 case TargetOpcode::G_ZEXT:
6302 case TargetOpcode::G_ANYEXT:
6303 case TargetOpcode::G_TRUNC:
6304 case TargetOpcode::G_FPTRUNC:
6305 case TargetOpcode::G_FPEXT:
6306 case TargetOpcode::G_FPTOSI:
6307 case TargetOpcode::G_FPTOUI:
6308 case TargetOpcode::G_FPTOSI_SAT:
6309 case TargetOpcode::G_FPTOUI_SAT:
6310 case TargetOpcode::G_SITOFP:
6311 case TargetOpcode::G_UITOFP: {
6319 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6323 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6331 case TargetOpcode::G_ICMP:
6332 case TargetOpcode::G_FCMP: {
6341 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6346 case TargetOpcode::G_BITCAST: {
6350 LLT SrcTy =
MRI.getType(
MI.getOperand(1).getReg());
6351 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6367 case TargetOpcode::G_VECREDUCE_FADD:
6368 case TargetOpcode::G_VECREDUCE_FMUL:
6369 case TargetOpcode::G_VECREDUCE_ADD:
6370 case TargetOpcode::G_VECREDUCE_MUL:
6371 case TargetOpcode::G_VECREDUCE_AND:
6372 case TargetOpcode::G_VECREDUCE_OR:
6373 case TargetOpcode::G_VECREDUCE_XOR:
6374 case TargetOpcode::G_VECREDUCE_SMAX:
6375 case TargetOpcode::G_VECREDUCE_SMIN:
6376 case TargetOpcode::G_VECREDUCE_UMAX:
6377 case TargetOpcode::G_VECREDUCE_UMIN: {
6378 LLT OrigTy =
MRI.getType(
MI.getOperand(1).getReg());
6381 auto NeutralElement = getNeutralElementForVecReduce(
6389 NeutralElement,
Idx);
6393 MO.
setReg(NewVec.getReg(0));
6405 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6407 unsigned MaskNumElts = Mask.size();
6411 if (MaskNumElts == SrcNumElts)
6414 if (MaskNumElts < SrcNumElts) {
6423 MI.getOperand(1).getReg(),
6424 MI.getOperand(2).getReg(), NewMask);
6425 MI.eraseFromParent();
6430 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6431 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6439 MOps1[0] =
MI.getOperand(1).getReg();
6440 MOps2[0] =
MI.getOperand(2).getReg();
6447 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6449 if (
Idx >=
static_cast<int>(SrcNumElts))
6450 Idx += PaddedMaskNumElts - SrcNumElts;
6455 if (MaskNumElts != PaddedMaskNumElts) {
6460 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6470 MI.eraseFromParent();
6476 unsigned int TypeIdx,
LLT MoreTy) {
6477 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6479 unsigned NumElts = DstTy.getNumElements();
6482 if (DstTy.isVector() && Src1Ty.isVector() &&
6483 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6491 if (DstTy != Src1Ty || DstTy != Src2Ty)
6499 for (
unsigned I = 0;
I != NumElts; ++
I) {
6501 if (
Idx <
static_cast<int>(NumElts))
6504 NewMask[
I] =
Idx - NumElts + WidenNumElts;
6509 MI.getOperand(1).getReg(),
6510 MI.getOperand(2).getReg(), NewMask);
6511 MI.eraseFromParent();
6520 unsigned SrcParts = Src1Regs.
size();
6521 unsigned DstParts = DstRegs.
size();
6523 unsigned DstIdx = 0;
6525 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
6526 DstRegs[DstIdx] = FactorSum;
6531 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
6533 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
6534 i <= std::min(DstIdx, SrcParts - 1); ++i) {
6536 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
6540 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
6541 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
6543 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
6553 if (DstIdx != DstParts - 1) {
6555 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
6556 FactorSum = Uaddo.
getReg(0);
6557 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).
getReg(0);
6558 for (
unsigned i = 2; i < Factors.
size(); ++i) {
6560 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
6561 FactorSum = Uaddo.
getReg(0);
6563 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
6567 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
6568 for (
unsigned i = 2; i < Factors.
size(); ++i)
6569 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
6572 CarrySumPrevDstIdx = CarrySum;
6573 DstRegs[DstIdx] = FactorSum;
6585 LLT DstType =
MRI.getType(DstReg);
6590 unsigned Opcode =
MI.getOpcode();
6591 unsigned OpO, OpE, OpF;
6593 case TargetOpcode::G_SADDO:
6594 case TargetOpcode::G_SADDE:
6595 case TargetOpcode::G_UADDO:
6596 case TargetOpcode::G_UADDE:
6597 case TargetOpcode::G_ADD:
6598 OpO = TargetOpcode::G_UADDO;
6599 OpE = TargetOpcode::G_UADDE;
6600 OpF = TargetOpcode::G_UADDE;
6601 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
6602 OpF = TargetOpcode::G_SADDE;
6604 case TargetOpcode::G_SSUBO:
6605 case TargetOpcode::G_SSUBE:
6606 case TargetOpcode::G_USUBO:
6607 case TargetOpcode::G_USUBE:
6608 case TargetOpcode::G_SUB:
6609 OpO = TargetOpcode::G_USUBO;
6610 OpE = TargetOpcode::G_USUBE;
6611 OpF = TargetOpcode::G_USUBE;
6612 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
6613 OpF = TargetOpcode::G_SSUBE;
6620 unsigned NumDefs =
MI.getNumExplicitDefs();
6621 Register Src1 =
MI.getOperand(NumDefs).getReg();
6622 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
6625 CarryDst =
MI.getOperand(1).getReg();
6626 if (
MI.getNumOperands() == NumDefs + 3)
6627 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
6629 LLT RegTy =
MRI.getType(
MI.getOperand(0).getReg());
6630 LLT LeftoverTy, DummyTy;
6632 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
6637 int NarrowParts = Src1Regs.
size();
6638 Src1Regs.
append(Src1Left);
6639 Src2Regs.
append(Src2Left);
6642 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
6644 MRI.createGenericVirtualRegister(
MRI.getType(Src1Regs[i]));
6647 if (i == e - 1 && CarryDst)
6648 CarryOut = CarryDst;
6654 {Src1Regs[i], Src2Regs[i]});
6655 }
else if (i == e - 1) {
6657 {Src1Regs[i], Src2Regs[i], CarryIn});
6660 {Src1Regs[i], Src2Regs[i], CarryIn});
6666 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
6667 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
6668 ArrayRef(DstRegs).drop_front(NarrowParts));
6670 MI.eraseFromParent();
6676 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
6678 LLT Ty =
MRI.getType(DstReg);
6684 if (
Size % NarrowSize != 0)
6687 unsigned NumParts =
Size / NarrowSize;
6688 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
6689 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
6695 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
6700 MI.eraseFromParent();
6710 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
6713 LLT SrcTy =
MRI.getType(Src);
6724 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
6737 int64_t SizeOp1 =
MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
6740 if (SizeOp1 % NarrowSize != 0)
6742 int NumParts = SizeOp1 / NarrowSize;
6745 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
6749 uint64_t OpStart =
MI.getOperand(2).getImm();
6750 uint64_t OpSize =
MRI.getType(OpReg).getSizeInBits();
6751 for (
int i = 0; i < NumParts; ++i) {
6752 unsigned SrcStart = i * NarrowSize;
6754 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
6757 }
else if (SrcStart == OpStart && NarrowTy ==
MRI.getType(OpReg)) {
6765 int64_t ExtractOffset;
6767 if (OpStart < SrcStart) {
6769 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
6771 ExtractOffset = OpStart - SrcStart;
6772 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
6776 if (ExtractOffset != 0 || SegSize != NarrowSize) {
6786 if (
MRI.getType(DstReg).isVector())
6788 else if (DstRegs.
size() > 1)
6792 MI.eraseFromParent();
6804 LLT RegTy =
MRI.getType(
MI.getOperand(0).getReg());
6806 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
6809 SrcRegs.
append(LeftoverRegs);
6813 uint64_t OpStart =
MI.getOperand(3).getImm();
6814 uint64_t OpSize =
MRI.getType(OpReg).getSizeInBits();
6815 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
6816 unsigned DstStart =
I * NarrowSize;
6818 if (DstStart == OpStart && NarrowTy ==
MRI.getType(OpReg)) {
6826 if (
MRI.getType(SrcRegs[
I]) == LeftoverTy) {
6828 SrcReg =
MRI.createGenericVirtualRegister(NarrowTy);
6832 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
6840 int64_t ExtractOffset, InsertOffset;
6842 if (OpStart < DstStart) {
6844 ExtractOffset = DstStart - OpStart;
6845 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
6847 InsertOffset = OpStart - DstStart;
6850 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
6854 if (ExtractOffset != 0 || SegSize != OpSize) {
6860 Register DstReg =
MRI.createGenericVirtualRegister(NarrowTy);
6874 MI.eraseFromParent();
6882 LLT DstTy =
MRI.getType(DstReg);
6884 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
6890 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
6895 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
6899 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
6901 {Src0Regs[I], Src1Regs[I]});
6905 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
6908 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
6909 DstLeftoverRegs.
push_back(Inst.getReg(0));
6912 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
6913 LeftoverTy, DstLeftoverRegs);
6915 MI.eraseFromParent();
6925 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
6927 LLT DstTy =
MRI.getType(DstReg);
6932 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
6933 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
6934 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
6936 MI.eraseFromParent();
6946 Register CondReg =
MI.getOperand(1).getReg();
6947 LLT CondTy =
MRI.getType(CondReg);
6952 LLT DstTy =
MRI.getType(DstReg);
6958 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
6963 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
6967 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
6969 CondReg, Src1Regs[
I], Src2Regs[
I]);
6973 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
6975 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
6979 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
6980 LeftoverTy, DstLeftoverRegs);
6982 MI.eraseFromParent();
6992 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6996 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
6999 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7001 auto C_0 =
B.buildConstant(NarrowTy, 0);
7003 UnmergeSrc.getReg(1), C_0);
7004 auto LoCTLZ = IsUndef ?
7005 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7006 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7007 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7008 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7009 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7010 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7012 MI.eraseFromParent();
7025 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7029 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7032 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7034 auto C_0 =
B.buildConstant(NarrowTy, 0);
7036 UnmergeSrc.getReg(0), C_0);
7037 auto HiCTTZ = IsUndef ?
7038 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7039 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7040 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7041 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7042 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7043 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7045 MI.eraseFromParent();
7058 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7068 MI.eraseFromParent();
7083 LLT ExpTy =
MRI.getType(ExpReg);
7088 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7089 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7090 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7091 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7093 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7095 MI.getOperand(2).setReg(Trunc.getReg(0));
7102 unsigned Opc =
MI.getOpcode();
7111 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7114 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7118 case TargetOpcode::G_CTLZ: {
7119 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7122 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7130 MI.eraseFromParent();
7146 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7150 Op = MIBOp.getReg(0);
7155 MI.eraseFromParent();
7158 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7161 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7165 case TargetOpcode::G_CTTZ: {
7166 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7169 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7178 MI.eraseFromParent();
7189 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7190 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7194 MI.eraseFromParent();
7198 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7199 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7203 case TargetOpcode::G_CTPOP: {
7205 LLT Ty =
MRI.getType(SrcReg);
7214 auto C_1 =
B.buildConstant(Ty, 1);
7215 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7217 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7218 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7219 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7223 auto C_2 =
B.buildConstant(Ty, 2);
7224 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7226 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7227 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7228 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7229 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7236 auto C_4 =
B.buildConstant(Ty, 4);
7237 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7238 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7240 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7241 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7243 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7249 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7251 auto IsMulSupported = [
this](
const LLT Ty) {
7252 auto Action = LI.
getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7255 if (IsMulSupported(Ty)) {
7256 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7257 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7259 auto ResTmp = B8Count;
7260 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7261 auto ShiftC =
B.buildConstant(Ty, Shift);
7262 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7263 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7265 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7267 MI.eraseFromParent();
7280 const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(
C);
7288 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7289 LLT Ty =
MRI.getType(Dst);
7290 LLT ShTy =
MRI.getType(Z);
7297 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7298 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7321 MI.eraseFromParent();
7327 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7328 LLT Ty =
MRI.getType(Dst);
7329 LLT ShTy =
MRI.getType(Z);
7332 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7376 MI.eraseFromParent();
7387 LLT Ty =
MRI.getType(Dst);
7388 LLT ShTy =
MRI.getType(
MI.getOperand(3).getReg());
7390 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7391 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7395 return lowerFunnelShiftAsShifts(
MI);
7399 if (Result == UnableToLegalize)
7400 return lowerFunnelShiftAsShifts(
MI);
7405 auto [Dst, Src] =
MI.getFirst2Regs();
7406 LLT DstTy =
MRI.getType(Dst);
7407 LLT SrcTy =
MRI.getType(Src);
7419 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7433 {UnmergeSrc.getReg(0)});
7435 {UnmergeSrc.getReg(1)});
7440 MI.eraseFromParent();
7457 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7461 LLT DstTy =
MRI.getType(DstReg);
7462 LLT SrcTy =
MRI.getType(SrcReg);
7495 MI.eraseFromParent();
7504 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7506 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7507 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7510 MI.eraseFromParent();
7515 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7517 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
7518 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7523 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7526 return lowerRotateWithReverseRotate(
MI);
7529 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7530 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7531 bool IsFShLegal =
false;
7532 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
7533 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
7537 MI.eraseFromParent();
7542 return buildFunnelShift(FShOpc, Dst, Src, Amt);
7545 return buildFunnelShift(RevFsh, Dst, Src, Amt);
7550 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
7551 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
7552 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
7558 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
7559 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
7561 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
7567 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
7568 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
7570 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
7572 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
7576 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
7577 MI.eraseFromParent();
7585 auto [Dst, Src] =
MI.getFirst2Regs();
7635 MI.eraseFromParent();
7643 auto [Dst, Src] =
MI.getFirst2Regs();
7670 MI.eraseFromParent();
7678 auto [Dst, Src] =
MI.getFirst2Regs();
7695 auto TwoP52P84 = llvm::bit_cast<double>(UINT64_C(0x4530000000100000));
7707 MI.eraseFromParent();
7717 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
7723 MI.eraseFromParent();
7728 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
7734 MI.eraseFromParent();
7758 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
7768 MI.eraseFromParent();
7796 MI.eraseFromParent();
7804 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
7808 if (SrcTy !=
S64 && SrcTy !=
S32)
7810 if (DstTy !=
S32 && DstTy !=
S64)
7839 MI.eraseFromParent();
7844 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
7903 MI.eraseFromParent();
7909 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
7911 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
7912 unsigned SatWidth = DstTy.getScalarSizeInBits();
7916 APInt MinInt, MaxInt;
7939 if (AreExactFloatBounds) {
7956 MI.eraseFromParent();
7963 DstTy.changeElementSize(1), Src, Src);
7966 MI.eraseFromParent();
7993 MI.eraseFromParent();
8001 DstTy.changeElementSize(1), Src, Src);
8003 MI.eraseFromParent();
8013 auto [Dst, Src] =
MI.getFirst2Regs();
8017 if (
MRI.getType(Src).isVector())
8021 unsigned Flags =
MI.getFlags();
8024 MI.eraseFromParent();
8028 const unsigned ExpMask = 0x7ff;
8029 const unsigned ExpBiasf64 = 1023;
8030 const unsigned ExpBiasf16 = 15;
8119 MI.eraseFromParent();
8125 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8136 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8137 LLT Ty =
MRI.getType(Dst);
8141 MI.eraseFromParent();
8147 case TargetOpcode::G_SMIN:
8149 case TargetOpcode::G_SMAX:
8151 case TargetOpcode::G_UMIN:
8153 case TargetOpcode::G_UMAX:
8161 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8164 LLT CmpType =
MRI.getType(Dst).changeElementSize(1);
8169 MI.eraseFromParent();
8178 LLT DstTy =
MRI.getType(Dst);
8179 LLT SrcTy =
MRI.getType(Cmp->getReg(1));
8209 unsigned BoolExtOp =
8216 MI.eraseFromParent();
8222 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8223 const int Src0Size = Src0Ty.getScalarSizeInBits();
8224 const int Src1Size = Src1Ty.getScalarSizeInBits();
8234 if (Src0Ty == Src1Ty) {
8236 }
else if (Src0Size > Src1Size) {
8251 unsigned Flags =
MI.getFlags();
8258 MI.eraseFromParent();
8269 switch (
MI.getOpcode()) {
8270 case TargetOpcode::G_FMINNUM:
8271 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8273 case TargetOpcode::G_FMINIMUMNUM:
8274 NewOp = TargetOpcode::G_FMINNUM;
8276 case TargetOpcode::G_FMAXNUM:
8277 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8279 case TargetOpcode::G_FMAXIMUMNUM:
8280 NewOp = TargetOpcode::G_FMAXNUM;
8286 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8287 LLT Ty =
MRI.getType(Dst);
8306 MI.eraseFromParent();
8313 LLT Ty =
MRI.getType(DstReg);
8314 unsigned Flags =
MI.getFlags();
8319 MI.eraseFromParent();
8325 auto [DstReg,
X] =
MI.getFirst2Regs();
8326 const unsigned Flags =
MI.getFlags();
8327 const LLT Ty =
MRI.getType(DstReg);
8353 MI.eraseFromParent();
8358 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8359 unsigned Flags =
MI.getFlags();
8360 LLT Ty =
MRI.getType(DstReg);
8371 SrcReg, Zero, Flags);
8373 SrcReg, Trunc, Flags);
8378 MI.eraseFromParent();
8384 const unsigned NumOps =
MI.getNumOperands();
8385 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8386 unsigned PartSize = Src0Ty.getSizeInBits();
8391 for (
unsigned I = 2;
I != NumOps; ++
I) {
8392 const unsigned Offset = (
I - 1) * PartSize;
8397 Register NextResult =
I + 1 == NumOps && WideTy == DstTy ? DstReg :
8398 MRI.createGenericVirtualRegister(WideTy);
8403 ResultReg = NextResult;
8406 if (DstTy.isPointer()) {
8408 DstTy.getAddressSpace())) {
8416 MI.eraseFromParent();
8422 const unsigned NumDst =
MI.getNumOperands() - 1;
8423 Register SrcReg =
MI.getOperand(NumDst).getReg();
8424 Register Dst0Reg =
MI.getOperand(0).getReg();
8425 LLT DstTy =
MRI.getType(Dst0Reg);
8434 LLT IntTy =
MRI.getType(SrcReg);
8439 unsigned Offset = DstSize;
8440 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
8446 MI.eraseFromParent();
8465 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
8466 InsertVal =
MI.getOperand(2).getReg();
8470 LLT VecTy =
MRI.getType(SrcVec);
8480 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
8486 MI.eraseFromParent();
8491 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
8509 int64_t
Offset = IdxVal * EltBytes;
8528 MI.eraseFromParent();
8534 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
8535 MI.getFirst3RegLLTs();
8543 for (
int Idx : Mask) {
8545 if (!Undef.isValid())
8551 if (Src0Ty.isScalar()) {
8554 int NumElts = Src0Ty.getNumElements();
8555 Register SrcVec =
Idx < NumElts ? Src0Reg : Src1Reg;
8556 int ExtractIdx =
Idx < NumElts ?
Idx :
Idx - NumElts;
8563 if (DstTy.isVector())
8567 MI.eraseFromParent();
8573 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
8574 MI.getFirst4RegLLTs();
8576 if (VecTy.isScalableVector())
8595 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
8601 std::optional<APInt> PassthruSplatVal =
8604 if (PassthruSplatVal.has_value()) {
8607 }
else if (HasPassthru) {
8619 unsigned NumElmts = VecTy.getNumElements();
8620 for (
unsigned I = 0;
I < NumElmts; ++
I) {
8635 if (HasPassthru &&
I == NumElmts - 1) {
8641 {OutPos, EndOfVector});
8654 MI.eraseFromParent();
8671 if (Alignment >
Align(1)) {
8683 const auto &MF = *
MI.getMF();
8689 Register AllocSize =
MI.getOperand(1).getReg();
8692 LLT PtrTy =
MRI.getType(Dst);
8700 MI.eraseFromParent();
8711 MI.eraseFromParent();
8722 MI.eraseFromParent();
8728 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8729 unsigned Offset =
MI.getOperand(2).getImm();
8734 unsigned DstSize = DstTy.getSizeInBits();
8736 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
8743 for (
unsigned Idx =
Offset / SrcEltSize;
8747 if (SubVectorElts.
size() == 1)
8752 MI.eraseFromParent();
8757 if (DstTy.isScalar() &&
8760 LLT SrcIntTy = SrcTy;
8774 MI.eraseFromParent();
8782 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
8785 LLT DstTy =
MRI.getType(Src);
8786 LLT InsertTy =
MRI.getType(InsertSrc);
8794 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
8807 for (
unsigned i = 0;
Idx < (
Offset + InsertSize) / EltSize;
8809 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
8822 MI.eraseFromParent();
8836 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
8840 LLT IntDstTy = DstTy;
8866 MI.eraseFromParent();
8872 auto [Dst0, Dst0Ty, Dst1, Dst1Ty,
LHS, LHSTy,
RHS, RHSTy] =
8873 MI.getFirst4RegLLTs();
8874 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
8877 LLT BoolTy = Dst1Ty;
8879 Register NewDst0 =
MRI.cloneVirtualRegister(Dst0);
8896 auto ResultLowerThanLHS =
8904 MI.eraseFromParent();
8911 auto [Res,
LHS,
RHS] =
MI.getFirst3Regs();
8912 LLT Ty =
MRI.getType(Res);
8916 switch (
MI.getOpcode()) {
8919 case TargetOpcode::G_UADDSAT:
8922 BaseOp = TargetOpcode::G_ADD;
8924 case TargetOpcode::G_SADDSAT:
8927 BaseOp = TargetOpcode::G_ADD;
8929 case TargetOpcode::G_USUBSAT:
8932 BaseOp = TargetOpcode::G_SUB;
8934 case TargetOpcode::G_SSUBSAT:
8937 BaseOp = TargetOpcode::G_SUB;
8980 MI.eraseFromParent();
8986 auto [Res,
LHS,
RHS] =
MI.getFirst3Regs();
8987 LLT Ty =
MRI.getType(Res);
8991 unsigned OverflowOp;
8992 switch (
MI.getOpcode()) {
8995 case TargetOpcode::G_UADDSAT:
8998 OverflowOp = TargetOpcode::G_UADDO;
9000 case TargetOpcode::G_SADDSAT:
9003 OverflowOp = TargetOpcode::G_SADDO;
9005 case TargetOpcode::G_USUBSAT:
9008 OverflowOp = TargetOpcode::G_USUBO;
9010 case TargetOpcode::G_SSUBSAT:
9013 OverflowOp = TargetOpcode::G_SSUBO;
9019 Register Tmp = OverflowRes.getReg(0);
9020 Register Ov = OverflowRes.getReg(1);
9046 MI.eraseFromParent();
9052 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9053 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9054 "Expected shlsat opcode!");
9055 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9056 auto [Res,
LHS,
RHS] =
MI.getFirst3Regs();
9057 LLT Ty =
MRI.getType(Res);
9078 MI.eraseFromParent();
9083 auto [Dst, Src] =
MI.getFirst2Regs();
9084 const LLT Ty =
MRI.getType(Src);
9086 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9095 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9097 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9109 Res.getInstr()->getOperand(0).setReg(Dst);
9111 MI.eraseFromParent();
9118 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9121 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9122 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9123 return B.buildOr(Dst,
LHS,
RHS);
9128 auto [Dst, Src] =
MI.getFirst2Regs();
9129 const LLT SrcTy =
MRI.getType(Src);
9134 if (SrcTy.
isVector() && (VSize % 8 == 0) &&
9135 (LI.
isLegal({TargetOpcode::G_BITREVERSE,
9136 {LLT::fixed_vector(VSize / 8, 8),
9137 LLT::fixed_vector(VSize / 8, 8)}}))) {
9171 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9175 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9178 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9182 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9186 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9191 MI.eraseFromParent();
9199 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9200 int NameOpIdx = IsRead ? 1 : 0;
9201 int ValRegIndex = IsRead ? 0 : 1;
9203 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9204 const LLT Ty =
MRI.getType(ValReg);
9205 const MDString *RegStr = cast<MDString>(
9206 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9213 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9214 Fn,
MI.getDebugLoc()));
9218 MI.eraseFromParent();
9227 MI.eraseFromParent();
9233 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9234 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9236 LLT OrigTy =
MRI.getType(Result);
9243 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9249 MI.eraseFromParent();
9255 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9260 MI.eraseFromParent();
9265 MI.eraseFromParent();
9284 APInt ExpMask = Inf;
9302 LLT DstTyCopy = DstTy;
9317 Mask &= ~fcPosFinite;
9324 Mask &= ~fcNegFinite;
9335 Mask &= ~PartialCheck;
9344 else if (PartialCheck ==
fcZero)
9363 appendToRes(SubnormalRes);
9370 else if (PartialCheck ==
fcInf)
9383 if (PartialCheck ==
fcNan) {
9387 }
else if (PartialCheck ==
fcQNan) {
9397 Abs, InfWithQnanBitC);
9405 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
9408 APInt MaxExpMinusOne = ExpMask - ExpLSB;
9419 appendToRes(NormalRes);
9423 MI.eraseFromParent();
9429 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
9430 MI.getFirst4RegLLTs();
9432 bool IsEltPtr = DstTy.isPointerOrPointerVector();
9441 if (MaskTy.isScalar()) {
9455 if (DstTy.isVector()) {
9458 MaskReg = ShufSplat.
getReg(0);
9463 }
else if (!DstTy.isVector()) {
9468 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
9481 MI.eraseFromParent();
9487 unsigned Opcode =
MI.getOpcode();
9490 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
9491 : TargetOpcode::G_UDIV,
9492 {
MI.getOperand(0).
getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9494 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
9495 : TargetOpcode::G_UREM,
9496 {
MI.getOperand(1).
getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9497 MI.eraseFromParent();
9507 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
9514 MI.eraseFromParent();
9525 LLT Ty =
MRI.getType(SrcReg);
9529 MI.eraseFromParent();
9536 Register DestReg =
MI.getOperand(0).getReg();
9542 MI.eraseFromParent();
9550 LLT Ty =
MRI.getType(DstReg);
9558 MI.eraseFromParent();
9565 LLT SrcTy =
MRI.getType(SrcReg);
9566 LLT DstTy =
MRI.getType(SrcReg);
9585 Register ListPtr =
MI.getOperand(1).getReg();
9586 LLT PtrTy =
MRI.getType(ListPtr);
9595 const Align A(
MI.getOperand(2).getImm());
9602 VAList = AndDst.
getReg(0);
9609 LLT LLTTy =
MRI.getType(Dst);
9620 Align EltAlignment =
DL.getABITypeAlign(Ty);
9625 MI.eraseFromParent();
9640 unsigned Limit,
const MemOp &
Op,
9641 unsigned DstAS,
unsigned SrcAS,
9644 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
9654 if (
Op.isFixedDstAlign())
9662 unsigned NumMemOps = 0;
9666 while (TySize >
Size) {
9675 assert(NewTySize > 0 &&
"Could not find appropriate type");
9682 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
9684 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
9694 if (++NumMemOps > Limit)
9697 MemOps.push_back(Ty);
9709 if (!Ty.
isVector() && ValVRegAndVal) {
9710 APInt Scalar = ValVRegAndVal->Value.trunc(8);
9718 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
9741 auto &MF = *
MI.getParent()->getParent();
9746 assert(KnownLen != 0 &&
"Have a zero length memset length!");
9748 bool DstAlignCanChange =
false;
9754 DstAlignCanChange =
true;
9757 std::vector<LLT> MemOps;
9759 const auto &DstMMO = **
MI.memoperands_begin();
9763 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
9774 if (DstAlignCanChange) {
9777 Align NewAlign =
DL.getABITypeAlign(IRTy);
9778 if (NewAlign > Alignment) {
9779 Alignment = NewAlign;
9789 LLT LargestTy = MemOps[0];
9790 for (
unsigned i = 1; i < MemOps.size(); i++)
9792 LargestTy = MemOps[i];
9804 LLT PtrTy =
MRI.getType(Dst);
9805 unsigned DstOff = 0;
9806 unsigned Size = KnownLen;
9807 for (
unsigned I = 0;
I < MemOps.size();
I++) {
9810 if (TySize >
Size) {
9813 assert(
I == MemOps.size() - 1 &&
I != 0);
9814 DstOff -= TySize -
Size;
9825 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
9838 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
9841 MIB.buildStore(
Value,
Ptr, *StoreMMO);
9846 MI.eraseFromParent();
9852 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
9854 auto [Dst, Src, Len] =
MI.getFirst3Regs();
9856 const auto *MMOIt =
MI.memoperands_begin();
9858 bool IsVolatile =
MemOp->isVolatile();
9864 "inline memcpy with dynamic size is not yet supported");
9865 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
9866 if (KnownLen == 0) {
9867 MI.eraseFromParent();
9871 const auto &DstMMO = **
MI.memoperands_begin();
9872 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
9873 Align DstAlign = DstMMO.getBaseAlign();
9874 Align SrcAlign = SrcMMO.getBaseAlign();
9876 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
9883 Align SrcAlign,
bool IsVolatile) {
9884 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
9885 return lowerMemcpy(
MI, Dst, Src, KnownLen,
9886 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
9893 Align SrcAlign,
bool IsVolatile) {
9894 auto &MF = *
MI.getParent()->getParent();
9899 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
9901 bool DstAlignCanChange =
false;
9903 Align Alignment = std::min(DstAlign, SrcAlign);
9907 DstAlignCanChange =
true;
9913 std::vector<LLT> MemOps;
9915 const auto &DstMMO = **
MI.memoperands_begin();
9916 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
9922 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
9928 if (DstAlignCanChange) {
9931 Align NewAlign =
DL.getABITypeAlign(IRTy);
9936 if (!
TRI->hasStackRealignment(MF))
9938 NewAlign = std::min(NewAlign, *StackAlign);
9940 if (NewAlign > Alignment) {
9941 Alignment = NewAlign;
9949 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
9957 unsigned CurrOffset = 0;
9958 unsigned Size = KnownLen;
9959 for (
auto CopyTy : MemOps) {
9962 if (CopyTy.getSizeInBytes() >
Size)
9963 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
9974 if (CurrOffset != 0) {
9975 LLT SrcTy =
MRI.getType(Src);
9978 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
9980 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
9984 if (CurrOffset != 0) {
9985 LLT DstTy =
MRI.getType(Dst);
9986 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
9988 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
9989 CurrOffset += CopyTy.getSizeInBytes();
9990 Size -= CopyTy.getSizeInBytes();
9993 MI.eraseFromParent();
10001 auto &MF = *
MI.getParent()->getParent();
10006 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10008 bool DstAlignCanChange =
false;
10011 Align Alignment = std::min(DstAlign, SrcAlign);
10015 DstAlignCanChange =
true;
10018 std::vector<LLT> MemOps;
10020 const auto &DstMMO = **
MI.memoperands_begin();
10021 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10030 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10036 if (DstAlignCanChange) {
10039 Align NewAlign =
DL.getABITypeAlign(IRTy);
10044 if (!
TRI->hasStackRealignment(MF))
10046 NewAlign = std::min(NewAlign, *StackAlign);
10048 if (NewAlign > Alignment) {
10049 Alignment = NewAlign;
10057 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10063 unsigned CurrOffset = 0;
10065 for (
auto CopyTy : MemOps) {
10072 if (CurrOffset != 0) {
10073 LLT SrcTy =
MRI.getType(Src);
10076 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10078 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10079 CurrOffset += CopyTy.getSizeInBytes();
10083 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10084 LLT CopyTy = MemOps[
I];
10090 if (CurrOffset != 0) {
10091 LLT DstTy =
MRI.getType(Dst);
10094 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10096 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10099 MI.eraseFromParent();
10105 const unsigned Opc =
MI.getOpcode();
10108 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10109 Opc == TargetOpcode::G_MEMSET) &&
10110 "Expected memcpy like instruction");
10112 auto MMOIt =
MI.memoperands_begin();
10117 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10119 if (
Opc != TargetOpcode::G_MEMSET) {
10120 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10121 MemOp = *(++MMOIt);
10122 SrcAlign =
MemOp->getBaseAlign();
10127 if (!LenVRegAndVal)
10129 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10131 if (KnownLen == 0) {
10132 MI.eraseFromParent();
10136 if (MaxLen && KnownLen > MaxLen)
10139 bool IsVolatile =
MemOp->isVolatile();
10140 if (
Opc == TargetOpcode::G_MEMCPY) {
10141 auto &MF = *
MI.getParent()->getParent();
10145 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10148 if (
Opc == TargetOpcode::G_MEMMOVE)
10149 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10150 if (
Opc == TargetOpcode::G_MEMSET)
10151 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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
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
#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
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
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.
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.
bool hasAttributes() const
Return true if the builder has IR-level attributes.
LLVM_ABI AttrBuilder & removeAttribute(Attribute::AttrKind Val)
Remove an attribute from the builder.
LLVM_ABI AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
bool hasRetAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the return value.
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.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
bool isNonIntegralAddressSpace(unsigned AddrSpace) const
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.
bool isTailCall(const MachineInstr &MI) const override
bool isEquality() const
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.
constexpr bool isPointerVector() const
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 bool isPointerOrPointerVector() const
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 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 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 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)
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 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)
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 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 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 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 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.
virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const
Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while widening a constant of type Small...
bool isLegalOrCustom(const LegalityQuery &Query) const
virtual bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const
Called for instructions with the Custom LegalizationAction.
bool isLegal(const LegalityQuery &Query) const
virtual bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
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.
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing 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 buildFSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FSUB Op0, Op1.
MachineInstrBuilder buildFPTOSI(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_FPTOSI Src0.
MachineInstrBuilder buildFMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
MachineInstrBuilder buildAdd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ADD Op0, Op1.
MachineInstrBuilder buildUndef(const DstOp &Res)
Build and insert Res = IMPLICIT_DEF.
MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0)
Build and insert a bitwise not, NegOne = G_CONSTANT -1 Res = G_OR Op0, NegOne.
MachineInstrBuilder buildAShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildUnmerge(ArrayRef< LLT > Res, const SrcOp &Op)
Build and insert Res0, ... = G_UNMERGE_VALUES Op.
MachineInstrBuilder buildFAbs(const DstOp &Dst, const SrcOp &Src0, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FABS Op0.
MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_SELECT Tst, Op0, Op1.
MachineInstrBuilder buildZExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp)
Build and inserts Res = G_AND Op, LowBitsSet(ImmOp) Since there is no G_ZEXT_INREG like G_SEXT_INREG,...
MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index)
Build and insert Res0, ... = G_EXTRACT Src, Idx0.
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 buildInsertSubvector(const DstOp &Res, const SrcOp &Src0, const SrcOp &Src1, unsigned Index)
Build and insert Res = G_INSERT_SUBVECTOR Src0, Src1, Idx.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
MachineInstrBuilder buildCast(const DstOp &Dst, const SrcOp &Src)
Build and insert an appropriate cast between two registers of equal size.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_ICMP Pred, Op0, Op1.
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 buildFPTOUI(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_FPTOUI Src0.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildFPow(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Dst = G_FPOW Src0, Src1.
MachineInstrBuilder buildAnyExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Res = COPY Op depending on the differing sizes of Res and Op.
MachineInstrBuilder buildSExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_SEXT Op.
MachineInstrBuilder buildIntrinsicTrunc(const DstOp &Dst, const SrcOp &Src0, std::optional< unsigned > Flags=std::nullopt)
Build and insert Dst = G_INTRINSIC_TRUNC Src0.
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildSExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_SEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
MachineInstrBuilder buildShuffleSplat(const DstOp &Res, const SrcOp &Src)
Build and insert a vector splat of a scalar Src using a G_INSERT_VECTOR_ELT and G_SHUFFLE_VECTOR idio...
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 buildBSwap(const DstOp &Dst, const SrcOp &Src0)
Build and insert Dst = G_BSWAP Src0.
MachineInstrBuilder buildCTLZ_ZERO_UNDEF(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_CTLZ_ZERO_UNDEF Op0, Src0.
MachineInstrBuilder buildVScale(const DstOp &Res, unsigned MinElts)
Build and insert Res = G_VSCALE MinElts.
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.
unsigned getBoolExtOp(bool IsVec, bool IsFP) const
MachineInstrBuilder buildObjectPtrOffset(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1)
Build and insert an instruction with appropriate flags for addressing some offset of an object,...
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 buildCTLZ(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_CTLZ Op0, Src0.
MachineInstrBuilder buildSMax(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_SMAX Op0, Op1.
MachineInstrBuilder buildAssertZExt(const DstOp &Res, const SrcOp &Op, unsigned Size)
Build and insert Res = G_ASSERT_ZEXT Op, Size.
MachineInstrBuilder buildStrictFAdd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_STRICT_FADD Op0, Op1.
std::optional< MachineInstrBuilder > materializeObjectPtrOffset(Register &Res, Register Op0, const LLT ValueTy, uint64_t Value)
Materialize and insert an instruction with appropriate flags for addressing some offset of an object,...
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 buildExtractVectorElement(const DstOp &Res, const SrcOp &Val, const SrcOp &Idx)
Build and insert Res = G_EXTRACT_VECTOR_ELT Val, Idx.
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_PTR_ADD Op0, Op1.
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...
MachineInstrBuilder buildExtractVectorElementConstant(const DstOp &Res, const SrcOp &Val, const int Idx)
Build and insert Res = G_EXTRACT_VECTOR_ELT Val, Idx.
MachineInstrBuilder buildCTTZ_ZERO_UNDEF(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_CTTZ_ZERO_UNDEF Op0, Src0.
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildBitReverse(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITREVERSE Src.
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 buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
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.
MachineInstrBuilder buildPadVectorWithUndefElements(const DstOp &Res, const SrcOp &Op0)
Build and insert a, b, ..., x = G_UNMERGE_VALUES Op0 Res = G_BUILD_VECTOR a, b, .....
MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx)
Build and insert Res = G_FRAME_INDEX Idx.
MachineInstrBuilder buildCTPOP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_CTPOP Op0, Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildSMin(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_SMIN Op0, Op1.
MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src, const SrcOp &Op, unsigned Index)
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildFCopysign(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_FCOPYSIGN Op0, Op1.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
MachineInstrBuilder buildFNeg(const DstOp &Dst, const SrcOp &Src0, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FNEG Op0.
MachineInstrBuilder buildInsertVectorElement(const DstOp &Res, const SrcOp &Val, const SrcOp &Elt, const SrcOp &Idx)
Build and insert Res = G_INSERT_VECTOR_ELT Val, Elt, Idx.
MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineInstrBuilder buildDeleteTrailingVectorElements(const DstOp &Res, const SrcOp &Op0)
Build and insert a, b, ..., x, y, z = G_UNMERGE_VALUES Op0 Res = G_BUILD_VECTOR a,...
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 buildAtomicCmpXchg(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, MMO.
MachineInstrBuilder buildShuffleVector(const DstOp &Res, const SrcOp &Src1, const SrcOp &Src2, ArrayRef< int > Mask)
Build and insert Res = G_SHUFFLE_VECTOR Src1, Src2, Mask.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
MachineInstrBuilder buildExtractSubvector(const DstOp &Res, const SrcOp &Src, unsigned Index)
Build and insert Res = G_EXTRACT_SUBVECTOR Src, Idx0.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildSplatVector(const DstOp &Res, const SrcOp &Val)
Build and insert Res = G_SPLAT_VECTOR Val.
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.
MachineInstrBuilder buildMaskLowPtrBits(const DstOp &Res, const SrcOp &Op0, uint32_t NumBits)
Build and insert Res = G_PTRMASK Op0, G_CONSTANT (1 << NumBits) - 1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
MachineInstrBuilder buildUMin(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_UMIN Op0, Op1.
MachineInstrBuilder buildFCmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_FCMP PredOp0, Op1.
MachineInstrBuilder buildFAdd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FADD Op0, Op1.
MachineInstrBuilder buildPtrToInt(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_PTRTOINT instruction.
MachineInstrBuilder buildFCanonicalize(const DstOp &Dst, const SrcOp &Src0, std::optional< unsigned > Flags=std::nullopt)
Build and insert Dst = G_FCANONICALIZE Src0.
MachineInstrBuilder buildSExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp)
Build and insert Res = G_SEXT_INREG Op, ImmOp.
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.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isReturn(QueryType Type=AnyInBundle) const
bool isDebugInstr() const
unsigned getNumOperands() const
Retuns the total number of operands.
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,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
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 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 isSExtCheaperThanZExt(EVT FromTy, EVT ToTy) const
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
unsigned getMaxStoresPerMemcpy(bool OptSize) const
Get maximum # of store operations permitted for llvm.memcpy.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
virtual bool shouldExpandCmpUsingSelects(EVT VT) const
Should we expand [US]CMP nodes using two selects and two compares, or by doing arithmetic on boolean ...
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.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
BooleanContent getBooleanContents(bool isVec, bool isFloat) const
For targets without i1 registers, this gives the nature of the high-bits of boolean values held in ty...
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
unsigned getMaxStoresPerMemmove(bool OptSize) const
Get maximum # of store operations permitted for llvm.memmove.
Align getMinStackArgumentAlignment() const
Return the minimum stack alignment of an argument.
virtual bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const
Returns true if arguments should be sign-extended in lib calls.
unsigned getMaxStoresPerMemset(bool OptSize) const
Get maximum # of store operations permitted for llvm.memset.
LLT getVectorIdxLLT(const DataLayout &DL) const
Returns the type to be used for the index operand of: G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT,...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual Register getRegisterByName(const char *RegName, LLT Ty, const MachineFunction &MF) const
Return the register ID of the name passed in.
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 Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
LLVM Value Representation.
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 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.
@ 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.
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.
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 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.
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.
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.
@ Success
The lock was released successfully.
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...
@ 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.
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
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.
uint64_t value() const
This is a hole in the type system and should not be abused.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
LegalizeAction Action
The action to take or the final answer.
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)