43#define DEBUG_TYPE "legalizer"
56static std::pair<int, int>
62 unsigned NumParts =
Size / NarrowSize;
63 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
66 if (LeftoverSize == 0)
71 if (LeftoverSize % EltSize != 0)
80 return std::make_pair(NumParts, NumLeftover);
88 switch (Ty.getSizeInBits()) {
126 auto Step = LI.getAction(
MI, MRI);
127 switch (Step.Action) {
142 return bitcast(
MI, Step.TypeIdx, Step.NewType);
145 return lower(
MI, Step.TypeIdx, Step.NewType);
154 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
162void LegalizerHelper::insertParts(
Register DstReg,
184 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
186 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
187 return mergeMixedSubvectors(DstReg, AllRegs);
193 extractGCDType(GCDRegs, GCDTy, PartReg);
194 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
195 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
200 LLT Ty = MRI.getType(
Reg);
208void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
211 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
212 appendVectorElts(AllElts, PartRegs[i]);
215 if (!MRI.getType(Leftover).isVector())
218 appendVectorElts(AllElts, Leftover);
220 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
226 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
228 const int StartIdx = Regs.
size();
229 const int NumResults =
MI.getNumOperands() - 1;
231 for (
int I = 0;
I != NumResults; ++
I)
232 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
237 LLT SrcTy = MRI.getType(SrcReg);
238 if (SrcTy == GCDTy) {
244 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
251 LLT SrcTy = MRI.getType(SrcReg);
253 extractGCDType(Parts, GCDTy, SrcReg);
257LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
259 unsigned PadStrategy) {
264 int NumOrigSrc = VRegs.
size();
270 if (NumOrigSrc < NumParts * NumSubParts) {
271 if (PadStrategy == TargetOpcode::G_ZEXT)
272 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
273 else if (PadStrategy == TargetOpcode::G_ANYEXT)
274 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
276 assert(PadStrategy == TargetOpcode::G_SEXT);
281 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
297 for (
int I = 0;
I != NumParts; ++
I) {
298 bool AllMergePartsArePadding =
true;
301 for (
int J = 0; J != NumSubParts; ++J) {
302 int Idx =
I * NumSubParts + J;
303 if (Idx >= NumOrigSrc) {
304 SubMerge[J] = PadReg;
308 SubMerge[J] = VRegs[Idx];
311 AllMergePartsArePadding =
false;
317 if (AllMergePartsArePadding && !AllPadReg) {
318 if (PadStrategy == TargetOpcode::G_ANYEXT)
319 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
320 else if (PadStrategy == TargetOpcode::G_ZEXT)
321 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
330 Remerge[
I] = AllPadReg;
334 if (NumSubParts == 1)
335 Remerge[
I] = SubMerge[0];
337 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
340 if (AllMergePartsArePadding && !AllPadReg)
341 AllPadReg = Remerge[
I];
344 VRegs = std::move(Remerge);
348void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
350 LLT DstTy = MRI.getType(DstReg);
355 if (DstTy == LCMTy) {
356 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
360 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
369 UnmergeDefs[0] = DstReg;
370 for (
unsigned I = 1;
I != NumDefs; ++
I)
371 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
374 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
382#define RTLIBCASE_INT(LibcallPrefix) \
386 return RTLIB::LibcallPrefix##32; \
388 return RTLIB::LibcallPrefix##64; \
390 return RTLIB::LibcallPrefix##128; \
392 llvm_unreachable("unexpected size"); \
396#define RTLIBCASE(LibcallPrefix) \
400 return RTLIB::LibcallPrefix##32; \
402 return RTLIB::LibcallPrefix##64; \
404 return RTLIB::LibcallPrefix##80; \
406 return RTLIB::LibcallPrefix##128; \
408 llvm_unreachable("unexpected size"); \
413 case TargetOpcode::G_LROUND:
415 case TargetOpcode::G_LLROUND:
417 case TargetOpcode::G_MUL:
419 case TargetOpcode::G_SDIV:
421 case TargetOpcode::G_UDIV:
423 case TargetOpcode::G_SREM:
425 case TargetOpcode::G_UREM:
427 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
429 case TargetOpcode::G_FADD:
431 case TargetOpcode::G_FSUB:
433 case TargetOpcode::G_FMUL:
435 case TargetOpcode::G_FDIV:
437 case TargetOpcode::G_FEXP:
439 case TargetOpcode::G_FEXP2:
441 case TargetOpcode::G_FEXP10:
443 case TargetOpcode::G_FREM:
445 case TargetOpcode::G_FPOW:
447 case TargetOpcode::G_FPOWI:
449 case TargetOpcode::G_FMA:
451 case TargetOpcode::G_FSIN:
453 case TargetOpcode::G_FCOS:
455 case TargetOpcode::G_FTAN:
457 case TargetOpcode::G_FASIN:
459 case TargetOpcode::G_FACOS:
461 case TargetOpcode::G_FATAN:
463 case TargetOpcode::G_FATAN2:
465 case TargetOpcode::G_FSINH:
467 case TargetOpcode::G_FCOSH:
469 case TargetOpcode::G_FTANH:
471 case TargetOpcode::G_FSINCOS:
473 case TargetOpcode::G_FMODF:
475 case TargetOpcode::G_FLOG10:
477 case TargetOpcode::G_FLOG:
479 case TargetOpcode::G_FLOG2:
481 case TargetOpcode::G_FLDEXP:
483 case TargetOpcode::G_FCEIL:
485 case TargetOpcode::G_FFLOOR:
487 case TargetOpcode::G_FMINNUM:
489 case TargetOpcode::G_FMAXNUM:
491 case TargetOpcode::G_FMINIMUMNUM:
493 case TargetOpcode::G_FMAXIMUMNUM:
495 case TargetOpcode::G_FSQRT:
497 case TargetOpcode::G_FRINT:
499 case TargetOpcode::G_FNEARBYINT:
501 case TargetOpcode::G_INTRINSIC_TRUNC:
503 case TargetOpcode::G_INTRINSIC_ROUND:
505 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
507 case TargetOpcode::G_INTRINSIC_LRINT:
509 case TargetOpcode::G_INTRINSIC_LLRINT:
529 AttributeList CallerAttrs =
F.getAttributes();
530 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
531 .removeAttribute(Attribute::NoAlias)
532 .removeAttribute(Attribute::NonNull)
537 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
538 CallerAttrs.hasRetAttr(Attribute::SExt))
549 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
556 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
564 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
567 if (Ret->getNumImplicitOperands() != 1)
570 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
594 Info.OrigRet = Result;
597 (Result.Ty->isVoidTy() ||
603 if (!CLI.lowerCall(MIRBuilder, Info))
606 if (
MI && Info.LoweredTailCall) {
607 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
617 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
618 "Expected instr following MI to be return or debug inst?");
621 Next->eraseFromParent();
622 }
while (
MI->getNextNode());
636 const char *Name = TLI.getLibcallName(
Libcall);
640 return createLibcall(MIRBuilder, Name, Result, Args, CC, LocObserver,
MI);
652 Args.push_back({MO.getReg(), OpType, 0});
654 {
MI.getOperand(0).getReg(), OpType, 0}, Args,
661 MachineFunction &MF = *
MI.getMF();
667 LLT DstTy = MRI.getType(DstSin);
672 unsigned AddrSpace =
DL.getAllocaAddrSpace();
673 MachinePointerInfo PtrInfo;
691 if (LibcallResult != LegalizeResult::Legalized)
699 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
700 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
701 MI.eraseFromParent();
716 LLT DstTy = MRI.getType(DstFrac);
721 unsigned AddrSpace =
DL.getAllocaAddrSpace();
722 MachinePointerInfo PtrInfo;
731 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
734 if (LibcallResult != LegalizeResult::Legalized)
740 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
741 MI.eraseFromParent();
753 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
757 LLT OpLLT =
MRI.getType(Reg);
758 Type *OpTy =
nullptr;
763 Args.push_back({Reg, OpTy, 0});
768 RTLIB::Libcall RTLibcall;
769 unsigned Opc =
MI.getOpcode();
772 case TargetOpcode::G_BZERO:
773 RTLibcall = RTLIB::BZERO;
774 Name = TLI.getLibcallName(RTLibcall);
776 case TargetOpcode::G_MEMCPY:
777 RTLibcall = RTLIB::MEMCPY;
778 Name = TLI.getLibcallImplName(TLI.getMemcpyImpl()).data();
779 Args[0].Flags[0].setReturned();
781 case TargetOpcode::G_MEMMOVE:
782 RTLibcall = RTLIB::MEMMOVE;
783 Name = TLI.getLibcallName(RTLibcall);
784 Args[0].Flags[0].setReturned();
786 case TargetOpcode::G_MEMSET:
787 RTLibcall = RTLIB::MEMSET;
788 Name = TLI.getLibcallName(RTLibcall);
789 Args[0].Flags[0].setReturned();
803 Info.
CallConv = TLI.getLibcallCallingConv(RTLibcall);
807 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
811 if (!CLI.lowerCall(MIRBuilder, Info))
814 if (Info.LoweredTailCall) {
815 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
825 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
826 "Expected instr following MI to be return or debug inst?");
829 Next->eraseFromParent();
830 }
while (
MI.getNextNode());
840 unsigned Opc =
MI.getOpcode();
842 auto &MMO = AtomicMI.getMMO();
843 auto Ordering = MMO.getMergedOrdering();
844 LLT MemType = MMO.getMemoryType();
847 return RTLIB::UNKNOWN_LIBCALL;
849#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
851 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
853 case TargetOpcode::G_ATOMIC_CMPXCHG:
854 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
855 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
856 return getOutlineAtomicHelper(LC, Ordering, MemSize);
858 case TargetOpcode::G_ATOMICRMW_XCHG: {
859 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
860 return getOutlineAtomicHelper(LC, Ordering, MemSize);
862 case TargetOpcode::G_ATOMICRMW_ADD:
863 case TargetOpcode::G_ATOMICRMW_SUB: {
864 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
865 return getOutlineAtomicHelper(LC, Ordering, MemSize);
867 case TargetOpcode::G_ATOMICRMW_AND: {
868 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
869 return getOutlineAtomicHelper(LC, Ordering, MemSize);
871 case TargetOpcode::G_ATOMICRMW_OR: {
872 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
873 return getOutlineAtomicHelper(LC, Ordering, MemSize);
875 case TargetOpcode::G_ATOMICRMW_XOR: {
876 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
877 return getOutlineAtomicHelper(LC, Ordering, MemSize);
880 return RTLIB::UNKNOWN_LIBCALL;
893 unsigned Opc =
MI.getOpcode();
895 case TargetOpcode::G_ATOMIC_CMPXCHG:
896 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
899 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
900 MI.getFirst4RegLLTs();
903 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
904 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
905 NewLLT) =
MI.getFirst5RegLLTs();
915 case TargetOpcode::G_ATOMICRMW_XCHG:
916 case TargetOpcode::G_ATOMICRMW_ADD:
917 case TargetOpcode::G_ATOMICRMW_SUB:
918 case TargetOpcode::G_ATOMICRMW_AND:
919 case TargetOpcode::G_ATOMICRMW_OR:
920 case TargetOpcode::G_ATOMICRMW_XOR: {
921 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
924 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
928 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
943 const char *Name = TLI.getLibcallName(RTLibcall);
953 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
958 if (!CLI.lowerCall(MIRBuilder,
Info))
970 case TargetOpcode::G_FPEXT:
972 case TargetOpcode::G_FPTRUNC:
974 case TargetOpcode::G_FPTOSI:
976 case TargetOpcode::G_FPTOUI:
978 case TargetOpcode::G_SITOFP:
980 case TargetOpcode::G_UITOFP:
991 if (FromType->isIntegerTy()) {
993 Arg.
Flags[0].setSExt();
995 Arg.
Flags[0].setZExt();
1000 {
MI.getOperand(0).getReg(), ToType, 0}, Arg, LocObserver,
1004static RTLIB::Libcall
1006 RTLIB::Libcall RTLibcall;
1007 switch (
MI.getOpcode()) {
1008 case TargetOpcode::G_GET_FPENV:
1009 RTLibcall = RTLIB::FEGETENV;
1011 case TargetOpcode::G_SET_FPENV:
1012 case TargetOpcode::G_RESET_FPENV:
1013 RTLibcall = RTLIB::FESETENV;
1015 case TargetOpcode::G_GET_FPMODE:
1016 RTLibcall = RTLIB::FEGETMODE;
1018 case TargetOpcode::G_SET_FPMODE:
1019 case TargetOpcode::G_RESET_FPMODE:
1020 RTLibcall = RTLIB::FESETMODE;
1053 LLT StateTy = MRI.getType(Dst);
1056 MachinePointerInfo TempPtrInfo;
1060 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1066 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1067 LocObserver,
nullptr);
1074 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1093 LLT StateTy = MRI.getType(Src);
1096 MachinePointerInfo TempPtrInfo;
1105 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1110 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1111 LocObserver,
nullptr);
1117static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1119#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1123 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1125 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1127 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1129 llvm_unreachable("unexpected size"); \
1161 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1164 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1171 LLT DstTy = MRI.getType(DstReg);
1172 const auto Cond =
Cmp->getCond();
1177 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1182 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1186 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1193 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1199 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1201 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1214 const auto [OeqLibcall, OeqPred] =
1216 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1218 const auto [UnoLibcall, UnoPred] =
1220 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1235 const auto [OeqLibcall, OeqPred] =
1240 const auto [UnoLibcall, UnoPred] =
1245 if (NotOeq && NotUno)
1264 const auto [InversedLibcall, InversedPred] =
1266 if (!BuildLibcall(InversedLibcall,
1292 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1294 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1297 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1303 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}),
1309 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1311 switch (
MI.getOpcode()) {
1314 case TargetOpcode::G_MUL:
1315 case TargetOpcode::G_SDIV:
1316 case TargetOpcode::G_UDIV:
1317 case TargetOpcode::G_SREM:
1318 case TargetOpcode::G_UREM:
1319 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1320 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1328 case TargetOpcode::G_FADD:
1329 case TargetOpcode::G_FSUB:
1330 case TargetOpcode::G_FMUL:
1331 case TargetOpcode::G_FDIV:
1332 case TargetOpcode::G_FMA:
1333 case TargetOpcode::G_FPOW:
1334 case TargetOpcode::G_FREM:
1335 case TargetOpcode::G_FCOS:
1336 case TargetOpcode::G_FSIN:
1337 case TargetOpcode::G_FTAN:
1338 case TargetOpcode::G_FACOS:
1339 case TargetOpcode::G_FASIN:
1340 case TargetOpcode::G_FATAN:
1341 case TargetOpcode::G_FATAN2:
1342 case TargetOpcode::G_FCOSH:
1343 case TargetOpcode::G_FSINH:
1344 case TargetOpcode::G_FTANH:
1345 case TargetOpcode::G_FLOG10:
1346 case TargetOpcode::G_FLOG:
1347 case TargetOpcode::G_FLOG2:
1348 case TargetOpcode::G_FEXP:
1349 case TargetOpcode::G_FEXP2:
1350 case TargetOpcode::G_FEXP10:
1351 case TargetOpcode::G_FCEIL:
1352 case TargetOpcode::G_FFLOOR:
1353 case TargetOpcode::G_FMINNUM:
1354 case TargetOpcode::G_FMAXNUM:
1355 case TargetOpcode::G_FMINIMUMNUM:
1356 case TargetOpcode::G_FMAXIMUMNUM:
1357 case TargetOpcode::G_FSQRT:
1358 case TargetOpcode::G_FRINT:
1359 case TargetOpcode::G_FNEARBYINT:
1360 case TargetOpcode::G_INTRINSIC_TRUNC:
1361 case TargetOpcode::G_INTRINSIC_ROUND:
1362 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1363 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1367 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1375 case TargetOpcode::G_FSINCOS: {
1376 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1380 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1385 case TargetOpcode::G_FMODF: {
1386 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1390 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1395 case TargetOpcode::G_LROUND:
1396 case TargetOpcode::G_LLROUND:
1397 case TargetOpcode::G_INTRINSIC_LRINT:
1398 case TargetOpcode::G_INTRINSIC_LLRINT: {
1399 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1403 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1405 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1411 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1414 MI.eraseFromParent();
1417 case TargetOpcode::G_FPOWI:
1418 case TargetOpcode::G_FLDEXP: {
1419 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1423 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1425 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1430 {
MI.getOperand(1).getReg(), HLTy, 0},
1431 {
MI.getOperand(2).getReg(), ITy, 1}};
1432 Args[1].Flags[0].setSExt();
1435 Args, LocObserver, &
MI);
1440 case TargetOpcode::G_FPEXT:
1441 case TargetOpcode::G_FPTRUNC: {
1444 if (!FromTy || !ToTy)
1452 case TargetOpcode::G_FCMP: {
1456 MI.eraseFromParent();
1459 case TargetOpcode::G_FPTOSI:
1460 case TargetOpcode::G_FPTOUI: {
1464 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1465 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1473 case TargetOpcode::G_SITOFP:
1474 case TargetOpcode::G_UITOFP: {
1475 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1478 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1480 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1483 LocObserver, TLI, IsSigned);
1488 case TargetOpcode::G_ATOMICRMW_XCHG:
1489 case TargetOpcode::G_ATOMICRMW_ADD:
1490 case TargetOpcode::G_ATOMICRMW_SUB:
1491 case TargetOpcode::G_ATOMICRMW_AND:
1492 case TargetOpcode::G_ATOMICRMW_OR:
1493 case TargetOpcode::G_ATOMICRMW_XOR:
1494 case TargetOpcode::G_ATOMIC_CMPXCHG:
1495 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1501 case TargetOpcode::G_BZERO:
1502 case TargetOpcode::G_MEMCPY:
1503 case TargetOpcode::G_MEMMOVE:
1504 case TargetOpcode::G_MEMSET: {
1509 MI.eraseFromParent();
1512 case TargetOpcode::G_GET_FPENV:
1513 case TargetOpcode::G_GET_FPMODE: {
1519 case TargetOpcode::G_SET_FPENV:
1520 case TargetOpcode::G_SET_FPMODE: {
1526 case TargetOpcode::G_RESET_FPENV:
1527 case TargetOpcode::G_RESET_FPMODE: {
1536 MI.eraseFromParent();
1543 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1546 switch (
MI.getOpcode()) {
1549 case TargetOpcode::G_IMPLICIT_DEF: {
1551 LLT DstTy = MRI.getType(DstReg);
1559 if (SizeOp0 % NarrowSize != 0) {
1564 MI.eraseFromParent();
1568 int NumParts = SizeOp0 / NarrowSize;
1571 for (
int i = 0; i < NumParts; ++i)
1575 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1577 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1578 MI.eraseFromParent();
1581 case TargetOpcode::G_CONSTANT: {
1582 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1583 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1584 unsigned TotalSize = Ty.getSizeInBits();
1586 int NumParts = TotalSize / NarrowSize;
1589 for (
int I = 0;
I != NumParts; ++
I) {
1590 unsigned Offset =
I * NarrowSize;
1597 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1599 if (LeftoverBits != 0) {
1603 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1607 insertParts(
MI.getOperand(0).getReg(),
1608 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1610 MI.eraseFromParent();
1613 case TargetOpcode::G_SEXT:
1614 case TargetOpcode::G_ZEXT:
1615 case TargetOpcode::G_ANYEXT:
1617 case TargetOpcode::G_TRUNC: {
1621 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1623 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1627 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1628 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1629 MI.eraseFromParent();
1632 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1633 case TargetOpcode::G_FREEZE: {
1637 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1642 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1644 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1646 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1650 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1651 MI.eraseFromParent();
1654 case TargetOpcode::G_ADD:
1655 case TargetOpcode::G_SUB:
1656 case TargetOpcode::G_SADDO:
1657 case TargetOpcode::G_SSUBO:
1658 case TargetOpcode::G_SADDE:
1659 case TargetOpcode::G_SSUBE:
1660 case TargetOpcode::G_UADDO:
1661 case TargetOpcode::G_USUBO:
1662 case TargetOpcode::G_UADDE:
1663 case TargetOpcode::G_USUBE:
1665 case TargetOpcode::G_MUL:
1666 case TargetOpcode::G_UMULH:
1668 case TargetOpcode::G_EXTRACT:
1670 case TargetOpcode::G_INSERT:
1672 case TargetOpcode::G_LOAD: {
1674 Register DstReg = LoadMI.getDstReg();
1675 LLT DstTy = MRI.getType(DstReg);
1679 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1680 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1681 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1683 LoadMI.eraseFromParent();
1689 case TargetOpcode::G_ZEXTLOAD:
1690 case TargetOpcode::G_SEXTLOAD: {
1692 Register DstReg = LoadMI.getDstReg();
1693 Register PtrReg = LoadMI.getPointerReg();
1695 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1696 auto &MMO = LoadMI.getMMO();
1699 if (MemSize == NarrowSize) {
1701 }
else if (MemSize < NarrowSize) {
1702 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1703 }
else if (MemSize > NarrowSize) {
1713 LoadMI.eraseFromParent();
1716 case TargetOpcode::G_STORE: {
1719 Register SrcReg = StoreMI.getValueReg();
1720 LLT SrcTy = MRI.getType(SrcReg);
1721 if (SrcTy.isVector())
1724 int NumParts = SizeOp0 / NarrowSize;
1726 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1727 if (SrcTy.isVector() && LeftoverBits != 0)
1730 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1731 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1733 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1734 StoreMI.eraseFromParent();
1740 case TargetOpcode::G_SELECT:
1742 case TargetOpcode::G_AND:
1743 case TargetOpcode::G_OR:
1744 case TargetOpcode::G_XOR: {
1756 case TargetOpcode::G_SHL:
1757 case TargetOpcode::G_LSHR:
1758 case TargetOpcode::G_ASHR:
1760 case TargetOpcode::G_CTLZ:
1761 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1762 case TargetOpcode::G_CTTZ:
1763 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1764 case TargetOpcode::G_CTPOP:
1766 switch (
MI.getOpcode()) {
1767 case TargetOpcode::G_CTLZ:
1768 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1770 case TargetOpcode::G_CTTZ:
1771 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1773 case TargetOpcode::G_CTPOP:
1783 case TargetOpcode::G_INTTOPTR:
1791 case TargetOpcode::G_PTRTOINT:
1799 case TargetOpcode::G_PHI: {
1802 if (SizeOp0 % NarrowSize != 0)
1805 unsigned NumParts = SizeOp0 / NarrowSize;
1809 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1817 for (
unsigned i = 0; i < NumParts; ++i) {
1818 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1820 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1821 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1822 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1825 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1827 MI.eraseFromParent();
1830 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1831 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1835 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1841 case TargetOpcode::G_ICMP: {
1843 LLT SrcTy = MRI.getType(LHS);
1849 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1855 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1856 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1862 LLT ResTy = MRI.getType(Dst);
1867 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1869 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1870 auto LHS = std::get<0>(LHSAndRHS);
1871 auto RHS = std::get<1>(LHSAndRHS);
1872 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1879 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1880 auto LHS = std::get<0>(LHSAndRHS);
1881 auto RHS = std::get<1>(LHSAndRHS);
1882 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1883 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1884 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1885 TargetOpcode::G_ZEXT);
1892 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1893 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1894 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1899 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1903 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1908 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1912 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1915 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1918 LHSPartRegs[
I], RHSPartRegs[
I]);
1919 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1925 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1934 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1938 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1939 RHSLeftoverRegs[
I]);
1941 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1942 RHSLeftoverRegs[
I]);
1945 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1946 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1952 MI.eraseFromParent();
1955 case TargetOpcode::G_FCMP:
1964 case TargetOpcode::G_SEXT_INREG: {
1968 int64_t SizeInBits =
MI.getOperand(2).getImm();
1977 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
1978 MO1.
setReg(TruncMIB.getReg(0));
1981 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
1993 if (SizeOp0 % NarrowSize != 0)
1995 int NumParts = SizeOp0 / NarrowSize;
2003 for (
int i = 0; i < NumParts; ++i) {
2004 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2019 for (
int i = 0; i < NumParts; ++i) {
2022 PartialExtensionReg = DstRegs.
back();
2024 assert(PartialExtensionReg &&
2025 "Expected to visit partial extension before full");
2026 if (FullExtensionReg) {
2031 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2033 FullExtensionReg = DstRegs.
back();
2038 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2041 PartialExtensionReg = DstRegs.
back();
2047 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2048 MI.eraseFromParent();
2051 case TargetOpcode::G_BSWAP:
2052 case TargetOpcode::G_BITREVERSE: {
2053 if (SizeOp0 % NarrowSize != 0)
2058 unsigned NumParts = SizeOp0 / NarrowSize;
2059 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2062 for (
unsigned i = 0; i < NumParts; ++i) {
2063 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2064 {SrcRegs[NumParts - 1 - i]});
2068 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2071 MI.eraseFromParent();
2074 case TargetOpcode::G_PTR_ADD:
2075 case TargetOpcode::G_PTRMASK: {
2083 case TargetOpcode::G_FPTOUI:
2084 case TargetOpcode::G_FPTOSI:
2085 case TargetOpcode::G_FPTOUI_SAT:
2086 case TargetOpcode::G_FPTOSI_SAT:
2088 case TargetOpcode::G_FPEXT:
2095 case TargetOpcode::G_FLDEXP:
2096 case TargetOpcode::G_STRICT_FLDEXP:
2098 case TargetOpcode::G_VSCALE: {
2100 LLT Ty = MRI.getType(Dst);
2104 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2105 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2106 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2109 MI.eraseFromParent();
2116 LLT Ty = MRI.getType(Val);
2122 if (Ty.isPointer()) {
2123 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2125 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2131 if (Ty.isPointerVector())
2132 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2133 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2137 unsigned OpIdx,
unsigned ExtOpcode) {
2139 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2140 MO.
setReg(ExtB.getReg(0));
2146 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2147 MO.
setReg(ExtB.getReg(0));
2151 unsigned OpIdx,
unsigned TruncOpcode) {
2153 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2155 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2160 unsigned OpIdx,
unsigned ExtOpcode) {
2162 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2164 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2173 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2175 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2181 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2191 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2198LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2203 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2204 if (DstTy.isVector())
2207 LLT SrcTy =
MRI.getType(Src1Reg);
2208 const int DstSize = DstTy.getSizeInBits();
2209 const int SrcSize = SrcTy.getSizeInBits();
2211 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2213 unsigned NumOps =
MI.getNumOperands();
2214 unsigned NumSrc =
MI.getNumOperands() - 1;
2215 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2217 if (WideSize >= DstSize) {
2221 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2222 const unsigned Offset = (
I - 1) * PartSize;
2230 MRI.createGenericVirtualRegister(WideTy);
2235 ResultReg = NextResult;
2238 if (WideSize > DstSize)
2240 else if (DstTy.isPointer())
2243 MI.eraseFromParent();
2268 const int GCD = std::gcd(SrcSize, WideSize);
2278 if (GCD == SrcSize) {
2281 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2282 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2288 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2290 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2294 const int PartsPerGCD = WideSize / GCD;
2298 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2300 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2307 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2309 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2310 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2313 MI.eraseFromParent();
2318LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2323 int NumDst =
MI.getNumOperands() - 1;
2324 Register SrcReg =
MI.getOperand(NumDst).getReg();
2325 LLT SrcTy = MRI.getType(SrcReg);
2329 Register Dst0Reg =
MI.getOperand(0).getReg();
2330 LLT DstTy = MRI.getType(Dst0Reg);
2339 dbgs() <<
"Not casting non-integral address space integer\n");
2344 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2352 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2360 for (
int I = 1;
I != NumDst; ++
I) {
2361 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2362 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2366 MI.eraseFromParent();
2377 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2381 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2384 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2402 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2407 if (PartsPerRemerge == 1) {
2410 for (
int I = 0;
I != NumUnmerge; ++
I) {
2411 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2413 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2414 int Idx =
I * PartsPerUnmerge + J;
2416 MIB.addDef(
MI.getOperand(Idx).getReg());
2419 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2423 MIB.addUse(Unmerge.getReg(
I));
2426 SmallVector<Register, 16> Parts;
2427 for (
int J = 0; J != NumUnmerge; ++J)
2428 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2431 for (
int I = 0;
I != NumDst; ++
I) {
2432 for (
int J = 0; J < PartsPerRemerge; ++J) {
2433 const int Idx =
I * PartsPerRemerge + J;
2437 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2438 RemergeParts.
clear();
2442 MI.eraseFromParent();
2447LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2449 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2450 unsigned Offset =
MI.getOperand(2).getImm();
2453 if (SrcTy.
isVector() || DstTy.isVector())
2465 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2469 if (DstTy.isPointer())
2476 MI.eraseFromParent();
2481 LLT ShiftTy = SrcTy;
2490 MI.eraseFromParent();
2521LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2523 if (TypeIdx != 0 || WideTy.
isVector())
2533LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2537 std::optional<Register> CarryIn;
2538 switch (
MI.getOpcode()) {
2541 case TargetOpcode::G_SADDO:
2542 Opcode = TargetOpcode::G_ADD;
2543 ExtOpcode = TargetOpcode::G_SEXT;
2545 case TargetOpcode::G_SSUBO:
2546 Opcode = TargetOpcode::G_SUB;
2547 ExtOpcode = TargetOpcode::G_SEXT;
2549 case TargetOpcode::G_UADDO:
2550 Opcode = TargetOpcode::G_ADD;
2551 ExtOpcode = TargetOpcode::G_ZEXT;
2553 case TargetOpcode::G_USUBO:
2554 Opcode = TargetOpcode::G_SUB;
2555 ExtOpcode = TargetOpcode::G_ZEXT;
2557 case TargetOpcode::G_SADDE:
2558 Opcode = TargetOpcode::G_UADDE;
2559 ExtOpcode = TargetOpcode::G_SEXT;
2560 CarryIn =
MI.getOperand(4).getReg();
2562 case TargetOpcode::G_SSUBE:
2563 Opcode = TargetOpcode::G_USUBE;
2564 ExtOpcode = TargetOpcode::G_SEXT;
2565 CarryIn =
MI.getOperand(4).getReg();
2567 case TargetOpcode::G_UADDE:
2568 Opcode = TargetOpcode::G_UADDE;
2569 ExtOpcode = TargetOpcode::G_ZEXT;
2570 CarryIn =
MI.getOperand(4).getReg();
2572 case TargetOpcode::G_USUBE:
2573 Opcode = TargetOpcode::G_USUBE;
2574 ExtOpcode = TargetOpcode::G_ZEXT;
2575 CarryIn =
MI.getOperand(4).getReg();
2591 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2592 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2596 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2598 .buildInstr(Opcode, {WideTy, CarryOutTy},
2599 {LHSExt, RHSExt, *CarryIn})
2602 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2604 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2605 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2606 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2611 MI.eraseFromParent();
2616LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2618 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2619 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2620 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2621 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2622 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2635 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2642 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2646 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2647 {ShiftL, ShiftR},
MI.getFlags());
2652 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2655 MI.eraseFromParent();
2660LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2669 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2671 LLT SrcTy = MRI.getType(
LHS);
2672 LLT OverflowTy = MRI.getType(OriginalOverflow);
2679 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2680 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2681 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2688 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2690 MachineInstrBuilder Mulo;
2691 if (WideMulCanOverflow)
2692 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2693 {LeftOperand, RightOperand});
2695 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2700 MachineInstrBuilder ExtResult;
2707 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2711 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2714 if (WideMulCanOverflow) {
2722 MI.eraseFromParent();
2728 unsigned Opcode =
MI.getOpcode();
2732 case TargetOpcode::G_ATOMICRMW_XCHG:
2733 case TargetOpcode::G_ATOMICRMW_ADD:
2734 case TargetOpcode::G_ATOMICRMW_SUB:
2735 case TargetOpcode::G_ATOMICRMW_AND:
2736 case TargetOpcode::G_ATOMICRMW_OR:
2737 case TargetOpcode::G_ATOMICRMW_XOR:
2738 case TargetOpcode::G_ATOMICRMW_MIN:
2739 case TargetOpcode::G_ATOMICRMW_MAX:
2740 case TargetOpcode::G_ATOMICRMW_UMIN:
2741 case TargetOpcode::G_ATOMICRMW_UMAX:
2742 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2748 case TargetOpcode::G_ATOMIC_CMPXCHG:
2749 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2756 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2766 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2771 case TargetOpcode::G_EXTRACT:
2772 return widenScalarExtract(
MI, TypeIdx, WideTy);
2773 case TargetOpcode::G_INSERT:
2774 return widenScalarInsert(
MI, TypeIdx, WideTy);
2775 case TargetOpcode::G_MERGE_VALUES:
2776 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2777 case TargetOpcode::G_UNMERGE_VALUES:
2778 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2779 case TargetOpcode::G_SADDO:
2780 case TargetOpcode::G_SSUBO:
2781 case TargetOpcode::G_UADDO:
2782 case TargetOpcode::G_USUBO:
2783 case TargetOpcode::G_SADDE:
2784 case TargetOpcode::G_SSUBE:
2785 case TargetOpcode::G_UADDE:
2786 case TargetOpcode::G_USUBE:
2787 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2788 case TargetOpcode::G_UMULO:
2789 case TargetOpcode::G_SMULO:
2790 return widenScalarMulo(
MI, TypeIdx, WideTy);
2791 case TargetOpcode::G_SADDSAT:
2792 case TargetOpcode::G_SSUBSAT:
2793 case TargetOpcode::G_SSHLSAT:
2794 case TargetOpcode::G_UADDSAT:
2795 case TargetOpcode::G_USUBSAT:
2796 case TargetOpcode::G_USHLSAT:
2797 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2798 case TargetOpcode::G_CTTZ:
2799 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2800 case TargetOpcode::G_CTLZ:
2801 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
2802 case TargetOpcode::G_CTPOP: {
2813 unsigned ExtOpc = Opcode == TargetOpcode::G_CTTZ ||
2814 Opcode == TargetOpcode::G_CTTZ_ZERO_UNDEF
2815 ? TargetOpcode::G_ANYEXT
2816 : TargetOpcode::G_ZEXT;
2817 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2818 LLT CurTy = MRI.getType(SrcReg);
2819 unsigned NewOpc = Opcode;
2820 if (NewOpc == TargetOpcode::G_CTTZ) {
2827 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2829 NewOpc = TargetOpcode::G_CTTZ_ZERO_UNDEF;
2834 if (Opcode == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
2844 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2846 if (Opcode == TargetOpcode::G_CTLZ) {
2849 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff));
2852 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2853 MI.eraseFromParent();
2856 case TargetOpcode::G_BSWAP: {
2860 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2861 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2862 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2865 MI.getOperand(0).setReg(DstExt);
2869 LLT Ty = MRI.getType(DstReg);
2871 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2872 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2878 case TargetOpcode::G_BITREVERSE: {
2882 LLT Ty = MRI.getType(DstReg);
2885 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2887 MI.getOperand(0).setReg(DstExt);
2890 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2891 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2896 case TargetOpcode::G_FREEZE:
2897 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2904 case TargetOpcode::G_ABS:
2911 case TargetOpcode::G_ADD:
2912 case TargetOpcode::G_AND:
2913 case TargetOpcode::G_MUL:
2914 case TargetOpcode::G_OR:
2915 case TargetOpcode::G_XOR:
2916 case TargetOpcode::G_SUB:
2917 case TargetOpcode::G_SHUFFLE_VECTOR:
2928 case TargetOpcode::G_SBFX:
2929 case TargetOpcode::G_UBFX:
2943 case TargetOpcode::G_SHL:
2959 case TargetOpcode::G_ROTR:
2960 case TargetOpcode::G_ROTL:
2969 case TargetOpcode::G_SDIV:
2970 case TargetOpcode::G_SREM:
2971 case TargetOpcode::G_SMIN:
2972 case TargetOpcode::G_SMAX:
2973 case TargetOpcode::G_ABDS:
2981 case TargetOpcode::G_SDIVREM:
2991 case TargetOpcode::G_ASHR:
2992 case TargetOpcode::G_LSHR:
2996 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
2997 : TargetOpcode::G_ZEXT;
3010 case TargetOpcode::G_UDIV:
3011 case TargetOpcode::G_UREM:
3012 case TargetOpcode::G_ABDU:
3019 case TargetOpcode::G_UDIVREM:
3028 case TargetOpcode::G_UMIN:
3029 case TargetOpcode::G_UMAX: {
3030 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3032 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3036 ? TargetOpcode::G_SEXT
3037 : TargetOpcode::G_ZEXT;
3047 case TargetOpcode::G_SELECT:
3057 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3064 case TargetOpcode::G_FPEXT:
3072 case TargetOpcode::G_FPTOSI:
3073 case TargetOpcode::G_FPTOUI:
3074 case TargetOpcode::G_INTRINSIC_LRINT:
3075 case TargetOpcode::G_INTRINSIC_LLRINT:
3076 case TargetOpcode::G_IS_FPCLASS:
3086 case TargetOpcode::G_SITOFP:
3096 case TargetOpcode::G_UITOFP:
3106 case TargetOpcode::G_FPTOSI_SAT:
3107 case TargetOpcode::G_FPTOUI_SAT:
3112 LLT Ty = MRI.getType(OldDst);
3113 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3115 MI.getOperand(0).setReg(ExtReg);
3116 uint64_t ShortBits = Ty.getScalarSizeInBits();
3119 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3130 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3131 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3139 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3147 case TargetOpcode::G_LOAD:
3148 case TargetOpcode::G_SEXTLOAD:
3149 case TargetOpcode::G_ZEXTLOAD:
3155 case TargetOpcode::G_STORE: {
3159 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3160 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3161 if (!Ty.isScalar()) {
3169 MI.setMemRefs(MF, {NewMMO});
3176 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3177 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3183 case TargetOpcode::G_CONSTANT: {
3186 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3187 MRI.getType(
MI.getOperand(0).getReg()));
3188 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3189 ExtOpc == TargetOpcode::G_ANYEXT) &&
3192 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3196 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3202 case TargetOpcode::G_FCONSTANT: {
3208 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3210 MI.eraseFromParent();
3213 case TargetOpcode::G_IMPLICIT_DEF: {
3219 case TargetOpcode::G_BRCOND:
3225 case TargetOpcode::G_FCMP:
3236 case TargetOpcode::G_ICMP:
3241 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3245 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3246 unsigned ExtOpcode =
3250 ? TargetOpcode::G_SEXT
3251 : TargetOpcode::G_ZEXT;
3258 case TargetOpcode::G_PTR_ADD:
3259 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3265 case TargetOpcode::G_PHI: {
3266 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3269 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3281 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3284 LLT VecTy = MRI.getType(VecReg);
3290 TargetOpcode::G_ANYEXT);
3304 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3320 LLT VecTy = MRI.getType(VecReg);
3339 case TargetOpcode::G_FADD:
3340 case TargetOpcode::G_FMUL:
3341 case TargetOpcode::G_FSUB:
3342 case TargetOpcode::G_FMA:
3343 case TargetOpcode::G_FMAD:
3344 case TargetOpcode::G_FNEG:
3345 case TargetOpcode::G_FABS:
3346 case TargetOpcode::G_FCANONICALIZE:
3347 case TargetOpcode::G_FMINNUM:
3348 case TargetOpcode::G_FMAXNUM:
3349 case TargetOpcode::G_FMINNUM_IEEE:
3350 case TargetOpcode::G_FMAXNUM_IEEE:
3351 case TargetOpcode::G_FMINIMUM:
3352 case TargetOpcode::G_FMAXIMUM:
3353 case TargetOpcode::G_FMINIMUMNUM:
3354 case TargetOpcode::G_FMAXIMUMNUM:
3355 case TargetOpcode::G_FDIV:
3356 case TargetOpcode::G_FREM:
3357 case TargetOpcode::G_FCEIL:
3358 case TargetOpcode::G_FFLOOR:
3359 case TargetOpcode::G_FCOS:
3360 case TargetOpcode::G_FSIN:
3361 case TargetOpcode::G_FTAN:
3362 case TargetOpcode::G_FACOS:
3363 case TargetOpcode::G_FASIN:
3364 case TargetOpcode::G_FATAN:
3365 case TargetOpcode::G_FATAN2:
3366 case TargetOpcode::G_FCOSH:
3367 case TargetOpcode::G_FSINH:
3368 case TargetOpcode::G_FTANH:
3369 case TargetOpcode::G_FLOG10:
3370 case TargetOpcode::G_FLOG:
3371 case TargetOpcode::G_FLOG2:
3372 case TargetOpcode::G_FRINT:
3373 case TargetOpcode::G_FNEARBYINT:
3374 case TargetOpcode::G_FSQRT:
3375 case TargetOpcode::G_FEXP:
3376 case TargetOpcode::G_FEXP2:
3377 case TargetOpcode::G_FEXP10:
3378 case TargetOpcode::G_FPOW:
3379 case TargetOpcode::G_INTRINSIC_TRUNC:
3380 case TargetOpcode::G_INTRINSIC_ROUND:
3381 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3385 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3391 case TargetOpcode::G_FMODF: {
3401 case TargetOpcode::G_FPOWI:
3402 case TargetOpcode::G_FLDEXP:
3403 case TargetOpcode::G_STRICT_FLDEXP: {
3405 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3426 case TargetOpcode::G_FFREXP: {
3439 case TargetOpcode::G_LROUND:
3440 case TargetOpcode::G_LLROUND:
3451 case TargetOpcode::G_INTTOPTR:
3459 case TargetOpcode::G_PTRTOINT:
3467 case TargetOpcode::G_BUILD_VECTOR: {
3471 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3477 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3485 case TargetOpcode::G_SEXT_INREG:
3494 case TargetOpcode::G_PTRMASK: {
3502 case TargetOpcode::G_VECREDUCE_ADD: {
3511 case TargetOpcode::G_VECREDUCE_FADD:
3512 case TargetOpcode::G_VECREDUCE_FMUL:
3513 case TargetOpcode::G_VECREDUCE_FMIN:
3514 case TargetOpcode::G_VECREDUCE_FMAX:
3515 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3516 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3521 LLT VecTy = MRI.getType(VecReg);
3528 case TargetOpcode::G_VSCALE: {
3535 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3540 case TargetOpcode::G_SPLAT_VECTOR: {
3549 case TargetOpcode::G_INSERT_SUBVECTOR: {
3557 LLT SubVecTy = MRI.getType(SubVec);
3561 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3562 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3563 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3567 auto SplatZero =
MIRBuilder.buildSplatVector(
3572 MI.eraseFromParent();
3581 auto Unmerge =
B.buildUnmerge(Ty, Src);
3582 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3591 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3593 LLT DstLLT =
MRI.getType(DstReg);
3605 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3614 MI.eraseFromParent();
3625 MI.eraseFromParent();
3632 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3633 if (SrcTy.isVector()) {
3637 if (DstTy.isVector()) {
3638 int NumDstElt = DstTy.getNumElements();
3639 int NumSrcElt = SrcTy.getNumElements();
3642 LLT DstCastTy = DstEltTy;
3643 LLT SrcPartTy = SrcEltTy;
3647 if (NumSrcElt < NumDstElt) {
3658 SrcPartTy = SrcEltTy;
3659 }
else if (NumSrcElt > NumDstElt) {
3671 DstCastTy = DstEltTy;
3676 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3680 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3681 MI.eraseFromParent();
3685 if (DstTy.isVector()) {
3688 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3689 MI.eraseFromParent();
3705 unsigned NewEltSize,
3706 unsigned OldEltSize) {
3707 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3708 LLT IdxTy =
B.getMRI()->getType(Idx);
3711 auto OffsetMask =
B.buildConstant(
3713 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3714 return B.buildShl(IdxTy, OffsetIdx,
3715 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3730 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3734 unsigned OldNumElts = SrcVecTy.getNumElements();
3741 if (NewNumElts > OldNumElts) {
3752 if (NewNumElts % OldNumElts != 0)
3756 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3760 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3763 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3765 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3766 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3767 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3768 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3769 NewOps[
I] = Elt.getReg(0);
3772 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3774 MI.eraseFromParent();
3778 if (NewNumElts < OldNumElts) {
3779 if (NewEltSize % OldEltSize != 0)
3801 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3802 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3805 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3809 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3810 ScaledIdx).getReg(0);
3818 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3820 MI.eraseFromParent();
3834 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3835 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3836 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3837 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3840 auto EltMask =
B.buildConstant(
3844 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3845 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3848 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3852 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3866 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3867 MI.getFirst4RegLLTs();
3879 if (NewNumElts < OldNumElts) {
3880 if (NewEltSize % OldEltSize != 0)
3889 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3890 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3893 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3897 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3898 ScaledIdx).getReg(0);
3908 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3909 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3913 MI.eraseFromParent();
3943 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3947 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3948 return UnableToLegalize;
3953 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3955 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3964 MI.eraseFromParent();
3982 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3983 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3993 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3994 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3996 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
3997 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
3999 MI.eraseFromParent();
4029 LLT DstTy = MRI.getType(Dst);
4030 LLT SrcTy = MRI.getType(Src);
4036 if (DstTy == CastTy)
4044 if (CastEltSize < DstEltSize)
4047 auto AdjustAmt = CastEltSize / DstEltSize;
4048 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4049 SrcTyMinElts % AdjustAmt != 0)
4054 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4055 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4058 ES->eraseFromParent();
4093 LLT DstTy = MRI.getType(Dst);
4094 LLT BigVecTy = MRI.getType(BigVec);
4095 LLT SubVecTy = MRI.getType(SubVec);
4097 if (DstTy == CastTy)
4112 if (CastEltSize < DstEltSize)
4115 auto AdjustAmt = CastEltSize / DstEltSize;
4116 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4117 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4123 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4124 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4126 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4129 ES->eraseFromParent();
4137 LLT DstTy = MRI.getType(DstReg);
4145 if (MemSizeInBits != MemStoreSizeInBits) {
4162 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4166 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4167 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4169 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4172 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4174 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4177 if (DstTy != LoadTy)
4185 if (
MIRBuilder.getDataLayout().isBigEndian())
4203 uint64_t LargeSplitSize, SmallSplitSize;
4208 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4215 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4218 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4229 if (Alignment.
value() * 8 > MemSizeInBits &&
4234 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4251 LLT PtrTy = MRI.getType(PtrReg);
4254 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4258 LargeSplitSize / 8);
4259 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4260 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4262 SmallPtr, *SmallMMO);
4264 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4265 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4267 if (AnyExtTy == DstTy)
4268 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4270 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4274 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4294 LLT SrcTy = MRI.getType(SrcReg);
4302 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4308 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4310 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4314 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4318 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4333 uint64_t LargeSplitSize, SmallSplitSize;
4340 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4343 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4352 if (SrcTy.isPointer()) {
4354 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4357 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4360 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4361 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4364 LLT PtrTy = MRI.getType(PtrReg);
4367 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4373 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4374 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4383 LLT SrcTy = MRI.getType(SrcReg);
4389 assert(SrcTy.isVector() &&
"Expect a vector store type");
4396 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4400 auto Elt =
MIRBuilder.buildExtractVectorElement(
4401 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4402 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4403 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4409 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4410 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4414 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4425 switch (
MI.getOpcode()) {
4426 case TargetOpcode::G_LOAD: {
4444 case TargetOpcode::G_STORE: {
4460 case TargetOpcode::G_SELECT: {
4464 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4466 dbgs() <<
"bitcast action not implemented for vector select\n");
4477 case TargetOpcode::G_AND:
4478 case TargetOpcode::G_OR:
4479 case TargetOpcode::G_XOR: {
4487 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4489 case TargetOpcode::G_INSERT_VECTOR_ELT:
4491 case TargetOpcode::G_CONCAT_VECTORS:
4493 case TargetOpcode::G_SHUFFLE_VECTOR:
4495 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4497 case TargetOpcode::G_INSERT_SUBVECTOR:
4505void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4515 switch(
MI.getOpcode()) {
4518 case TargetOpcode::G_FCONSTANT:
4520 case TargetOpcode::G_BITCAST:
4522 case TargetOpcode::G_SREM:
4523 case TargetOpcode::G_UREM: {
4524 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4526 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4527 {MI.getOperand(1), MI.getOperand(2)});
4529 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4531 MI.eraseFromParent();
4534 case TargetOpcode::G_SADDO:
4535 case TargetOpcode::G_SSUBO:
4537 case TargetOpcode::G_SADDE:
4539 case TargetOpcode::G_SSUBE:
4541 case TargetOpcode::G_UMULH:
4542 case TargetOpcode::G_SMULH:
4544 case TargetOpcode::G_SMULO:
4545 case TargetOpcode::G_UMULO: {
4548 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4549 LLT Ty = MRI.getType(Res);
4551 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4552 ? TargetOpcode::G_SMULH
4553 : TargetOpcode::G_UMULH;
4557 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4558 MI.removeOperand(1);
4561 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4569 if (Opcode == TargetOpcode::G_SMULH) {
4570 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4571 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4578 case TargetOpcode::G_FNEG: {
4579 auto [Res, SubByReg] =
MI.getFirst2Regs();
4580 LLT Ty = MRI.getType(Res);
4584 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4585 MI.eraseFromParent();
4588 case TargetOpcode::G_FSUB:
4589 case TargetOpcode::G_STRICT_FSUB: {
4590 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4591 LLT Ty = MRI.getType(Res);
4596 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4597 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4601 MI.eraseFromParent();
4604 case TargetOpcode::G_FMAD:
4606 case TargetOpcode::G_FFLOOR:
4608 case TargetOpcode::G_LROUND:
4609 case TargetOpcode::G_LLROUND: {
4612 LLT SrcTy = MRI.getType(SrcReg);
4613 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4616 MI.eraseFromParent();
4619 case TargetOpcode::G_INTRINSIC_ROUND:
4621 case TargetOpcode::G_FRINT: {
4624 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4627 case TargetOpcode::G_INTRINSIC_LRINT:
4628 case TargetOpcode::G_INTRINSIC_LLRINT: {
4631 LLT SrcTy = MRI.getType(SrcReg);
4633 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4635 MI.eraseFromParent();
4638 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4639 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4640 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4641 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4642 **
MI.memoperands_begin());
4644 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4645 MI.eraseFromParent();
4648 case TargetOpcode::G_LOAD:
4649 case TargetOpcode::G_SEXTLOAD:
4650 case TargetOpcode::G_ZEXTLOAD:
4652 case TargetOpcode::G_STORE:
4654 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4655 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4656 case TargetOpcode::G_CTLZ:
4657 case TargetOpcode::G_CTTZ:
4658 case TargetOpcode::G_CTPOP:
4661 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4663 Register NewRes = MRI.cloneVirtualRegister(Res);
4670 MI.eraseFromParent();
4674 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4675 const LLT CondTy = MRI.getType(CarryOut);
4676 const LLT Ty = MRI.getType(Res);
4678 Register NewRes = MRI.cloneVirtualRegister(Res);
4681 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4687 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4688 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4695 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4700 MI.eraseFromParent();
4704 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4709 MI.eraseFromParent();
4713 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4714 const LLT CondTy = MRI.getType(BorrowOut);
4715 const LLT Ty = MRI.getType(Res);
4718 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4724 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4725 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4732 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4733 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4735 MI.eraseFromParent();
4771 case G_MERGE_VALUES:
4773 case G_UNMERGE_VALUES:
4775 case TargetOpcode::G_SEXT_INREG: {
4776 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4777 int64_t SizeInBits =
MI.getOperand(2).getImm();
4779 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4780 LLT DstTy = MRI.getType(DstReg);
4781 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4784 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4785 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4786 MI.eraseFromParent();
4789 case G_EXTRACT_VECTOR_ELT:
4790 case G_INSERT_VECTOR_ELT:
4792 case G_SHUFFLE_VECTOR:
4794 case G_VECTOR_COMPRESS:
4796 case G_DYN_STACKALLOC:
4800 case G_STACKRESTORE:
4810 case G_READ_REGISTER:
4811 case G_WRITE_REGISTER:
4818 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4819 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4825 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4830 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4841 bool IsSigned =
MI.getOpcode() == G_ABDS;
4842 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4843 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4844 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4868 case G_MEMCPY_INLINE:
4869 return lowerMemcpyInline(
MI);
4880 case G_ATOMICRMW_SUB: {
4881 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4882 const LLT ValTy = MRI.getType(Val);
4886 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4887 MI.eraseFromParent();
4910 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4914 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4920 Align StackTypeAlign =
4927 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4928 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4933 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4945 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4948 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4959 "Converting bits to bytes lost precision");
4965 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4966 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4968 if (IdxTy != MRI.getType(Index))
4969 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4974 LLT PtrTy = MRI.getType(VecPtr);
4975 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4983 std::initializer_list<unsigned> NonVecOpIndices) {
4984 if (
MI.getNumMemOperands() != 0)
4987 LLT VecTy =
MRI.getType(
MI.getReg(0));
5001 if (!Ty.isVector()) {
5007 if (Ty.getNumElements() != NumElts)
5022 assert(Ty.isVector() &&
"Expected vector type");
5024 int NumParts, NumLeftover;
5025 std::tie(NumParts, NumLeftover) =
5028 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5029 for (
int i = 0; i < NumParts; ++i) {
5034 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5043 for (
unsigned i = 0; i <
N; ++i) {
5045 Ops.push_back(
Op.getReg());
5046 else if (
Op.isImm())
5047 Ops.push_back(
Op.getImm());
5048 else if (
Op.isPredicate())
5070 std::initializer_list<unsigned> NonVecOpIndices) {
5072 "Non-compatible opcode or not specified non-vector operands");
5073 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5075 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5076 unsigned NumDefs =
MI.getNumDefs();
5084 for (
unsigned i = 0; i < NumDefs; ++i) {
5085 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5093 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5094 ++UseIdx, ++UseNo) {
5097 MI.getOperand(UseIdx));
5106 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5110 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5112 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5113 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5116 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5117 Uses.push_back(InputOpsPieces[InputNo][i]);
5120 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5121 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5126 for (
unsigned i = 0; i < NumDefs; ++i)
5127 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5129 for (
unsigned i = 0; i < NumDefs; ++i)
5130 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5133 MI.eraseFromParent();
5140 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5142 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5143 unsigned NumDefs =
MI.getNumDefs();
5147 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5152 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5153 UseIdx += 2, ++UseNo) {
5161 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5163 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5164 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5166 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5169 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5170 Phi.addUse(InputOpsPieces[j][i]);
5171 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5181 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5183 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5186 MI.eraseFromParent();
5194 const int NumDst =
MI.getNumOperands() - 1;
5195 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5196 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5197 LLT SrcTy = MRI.getType(SrcReg);
5199 if (TypeIdx != 1 || NarrowTy == DstTy)
5206 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5209 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5223 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5224 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5225 const int PartsPerUnmerge = NumDst / NumUnmerge;
5227 for (
int I = 0;
I != NumUnmerge; ++
I) {
5228 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5230 for (
int J = 0; J != PartsPerUnmerge; ++J)
5231 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5232 MIB.addUse(Unmerge.getReg(
I));
5235 MI.eraseFromParent();
5242 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5246 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5248 if (NarrowTy == SrcTy)
5256 assert(SrcTy.isVector() &&
"Expected vector types");
5258 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5272 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5273 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5274 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5280 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5281 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5282 ++i,
Offset += NumNarrowTyElts) {
5285 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5288 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5289 MI.eraseFromParent();
5293 assert(TypeIdx == 0 &&
"Bad type index");
5294 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5309 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5310 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5312 for (
unsigned i = 0; i < NumParts; ++i) {
5314 for (
unsigned j = 0; j < NumElts; ++j)
5315 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5317 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5320 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5321 MI.eraseFromParent();
5329 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5331 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5333 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5335 InsertVal =
MI.getOperand(2).getReg();
5337 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5338 LLT VecTy = MRI.getType(SrcVec);
5344 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5348 MI.eraseFromParent();
5357 SplitPieces[IdxVal] = InsertVal;
5358 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5360 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5364 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5367 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5368 TargetOpcode::G_ANYEXT);
5372 LLT IdxTy = MRI.getType(Idx);
5373 int64_t PartIdx = IdxVal / NewNumElts;
5375 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5378 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5381 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5382 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5383 VecParts[PartIdx] = InsertPart.getReg(0);
5387 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5389 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5393 MI.eraseFromParent();
5413 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5425 LLT ValTy = MRI.getType(ValReg);
5434 int NumLeftover = -1;
5440 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5442 NumParts = NarrowRegs.
size();
5443 NumLeftover = NarrowLeftoverRegs.
size();
5450 LLT PtrTy = MRI.getType(AddrReg);
5453 unsigned TotalSize = ValTy.getSizeInBits();
5460 auto MMO = LdStMI.
getMMO();
5462 unsigned NumParts,
unsigned Offset) ->
unsigned {
5465 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5467 unsigned ByteOffset =
Offset / 8;
5470 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5477 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5478 ValRegs.push_back(Dst);
5479 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5481 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5490 unsigned HandledOffset =
5491 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5495 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5498 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5499 LeftoverTy, NarrowLeftoverRegs);
5513 switch (
MI.getOpcode()) {
5514 case G_IMPLICIT_DEF:
5530 case G_FCANONICALIZE:
5547 case G_INTRINSIC_LRINT:
5548 case G_INTRINSIC_LLRINT:
5549 case G_INTRINSIC_ROUND:
5550 case G_INTRINSIC_ROUNDEVEN:
5553 case G_INTRINSIC_TRUNC:
5581 case G_FMINNUM_IEEE:
5582 case G_FMAXNUM_IEEE:
5604 case G_CTLZ_ZERO_UNDEF:
5606 case G_CTTZ_ZERO_UNDEF:
5622 case G_ADDRSPACE_CAST:
5635 case G_STRICT_FLDEXP:
5644 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5649 case G_UNMERGE_VALUES:
5651 case G_BUILD_VECTOR:
5652 assert(TypeIdx == 0 &&
"not a vector type index");
5654 case G_CONCAT_VECTORS:
5658 case G_EXTRACT_VECTOR_ELT:
5659 case G_INSERT_VECTOR_ELT:
5668 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5669 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5671 case G_SHUFFLE_VECTOR:
5677 case G_INTRINSIC_FPTRUNC_ROUND:
5687 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5688 "Not a bitcast operation");
5693 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5695 unsigned NewElemCount =
5698 if (NewElemCount == 1) {
5701 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5708 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5717 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5718 MI.eraseFromParent();
5724 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5728 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5729 MI.getFirst3RegLLTs();
5732 if (DstTy != Src1Ty)
5734 if (DstTy != Src2Ty)
5749 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5765 unsigned InputUsed[2] = {-1U, -1U};
5766 unsigned FirstMaskIdx =
High * NewElts;
5767 bool UseBuildVector =
false;
5768 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5770 int Idx = Mask[FirstMaskIdx + MaskOffset];
5775 if (
Input >= std::size(Inputs)) {
5782 Idx -=
Input * NewElts;
5786 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5787 if (InputUsed[OpNo] ==
Input) {
5790 }
else if (InputUsed[OpNo] == -1U) {
5792 InputUsed[OpNo] =
Input;
5797 if (OpNo >= std::size(InputUsed)) {
5800 UseBuildVector =
true;
5805 Ops.push_back(Idx + OpNo * NewElts);
5808 if (UseBuildVector) {
5813 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5815 int Idx = Mask[FirstMaskIdx + MaskOffset];
5820 if (
Input >= std::size(Inputs)) {
5827 Idx -=
Input * NewElts;
5831 .buildExtractVectorElement(
5832 EltTy, Inputs[
Input],
5838 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5839 }
else if (InputUsed[0] == -1U) {
5841 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5842 }
else if (NewElts == 1) {
5843 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
5845 Register Op0 = Inputs[InputUsed[0]];
5849 : Inputs[InputUsed[1]];
5851 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5858 MI.eraseFromParent();
5871 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5877 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5880 const unsigned NumParts =
5882 : SrcTy.getNumElements();
5886 if (DstTy != NarrowTy)
5892 unsigned NumPartsLeft = NumParts;
5893 while (NumPartsLeft > 1) {
5894 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5897 .buildInstr(ScalarOpc, {NarrowTy},
5898 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5901 SplitSrcs = PartialResults;
5902 PartialResults.
clear();
5903 NumPartsLeft = SplitSrcs.
size();
5907 MI.eraseFromParent();
5912 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5913 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5916 MI.eraseFromParent();
5920 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5922 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5930 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5933 Register Acc = PartialReductions[0];
5934 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5935 if (Part == NumParts - 1) {
5937 {Acc, PartialReductions[Part]});
5940 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5944 MI.eraseFromParent();
5950 unsigned int TypeIdx,
5952 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5953 MI.getFirst3RegLLTs();
5954 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5958 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5959 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5960 "Unexpected vecreduce opcode");
5961 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5962 ? TargetOpcode::G_FADD
5963 : TargetOpcode::G_FMUL;
5966 unsigned NumParts = SrcTy.getNumElements();
5969 for (
unsigned i = 0; i < NumParts; i++)
5970 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5974 MI.eraseFromParent();
5981 unsigned ScalarOpc) {
5989 while (SplitSrcs.
size() > 1) {
5991 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
5999 SplitSrcs = std::move(PartialRdxs);
6003 MI.getOperand(1).setReg(SplitSrcs[0]);
6010 const LLT HalfTy,
const LLT AmtTy) {
6012 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6013 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6017 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6018 MI.eraseFromParent();
6024 unsigned VTBits = 2 * NVTBits;
6027 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6028 if (Amt.
ugt(VTBits)) {
6030 }
else if (Amt.
ugt(NVTBits)) {
6033 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6034 }
else if (Amt == NVTBits) {
6042 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6045 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6046 if (Amt.
ugt(VTBits)) {
6048 }
else if (Amt.
ugt(NVTBits)) {
6050 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6052 }
else if (Amt == NVTBits) {
6056 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6058 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6060 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6066 if (Amt.
ugt(VTBits)) {
6068 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6069 }
else if (Amt.
ugt(NVTBits)) {
6071 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6073 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6074 }
else if (Amt == NVTBits) {
6077 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6079 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6081 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6083 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6090 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6091 MI.eraseFromParent();
6107 LLT DstTy = MRI.getType(DstReg);
6112 LLT ShiftAmtTy = MRI.getType(Amt);
6114 if (DstEltSize % 2 != 0)
6130 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6141 const unsigned NewBitSize = DstEltSize / 2;
6153 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6155 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6156 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6159 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6160 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6162 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6167 switch (
MI.getOpcode()) {
6168 case TargetOpcode::G_SHL: {
6170 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6172 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6173 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6174 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6177 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6178 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6180 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6182 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6184 ResultRegs[0] =
Lo.getReg(0);
6185 ResultRegs[1] =
Hi.getReg(0);
6188 case TargetOpcode::G_LSHR:
6189 case TargetOpcode::G_ASHR: {
6191 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6193 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6194 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6195 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6199 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6202 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6203 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6205 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6209 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6211 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6213 ResultRegs[0] =
Lo.getReg(0);
6214 ResultRegs[1] =
Hi.getReg(0);
6221 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6222 MI.eraseFromParent();
6231 LLT TargetTy,
LLT ShiftAmtTy) {
6234 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6236 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6237 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6238 const bool NeedsInterWordShift = ShiftBits != 0;
6241 case TargetOpcode::G_SHL: {
6244 if (PartIdx < ShiftWords)
6247 unsigned SrcIdx = PartIdx - ShiftWords;
6248 if (!NeedsInterWordShift)
6249 return SrcParts[SrcIdx];
6254 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6258 return Hi.getReg(0);
6261 case TargetOpcode::G_LSHR: {
6262 unsigned SrcIdx = PartIdx + ShiftWords;
6263 if (SrcIdx >= NumParts)
6265 if (!NeedsInterWordShift)
6266 return SrcParts[SrcIdx];
6270 if (SrcIdx + 1 < NumParts) {
6271 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6275 return Lo.getReg(0);
6278 case TargetOpcode::G_ASHR: {
6280 unsigned SrcIdx = PartIdx + ShiftWords;
6281 if (SrcIdx >= NumParts)
6283 if (!NeedsInterWordShift)
6284 return SrcParts[SrcIdx];
6289 (SrcIdx == NumParts - 1)
6293 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6315 unsigned MainOpcode =
6316 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6320 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6329 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6330 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6332 auto IsZeroBitShift =
6340 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6341 : TargetOpcode::G_SHL;
6344 auto TargetBitsConst =
6346 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6351 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6356 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6358 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6362 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6375 LLT DstTy = MRI.getType(DstReg);
6379 const unsigned NumParts = DstBits / TargetBits;
6381 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6391 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6392 MI.eraseFromParent();
6397 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6398 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6404 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6408 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6411 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6412 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6416 for (
unsigned I = 0;
I < NumParts; ++
I)
6418 Params, TargetTy, ShiftAmtTy);
6420 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6421 MI.eraseFromParent();
6430 LLT DstTy = MRI.getType(DstReg);
6431 LLT ShiftAmtTy = MRI.getType(AmtReg);
6435 const unsigned NumParts = DstBits / TargetBits;
6437 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6454 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6466 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6467 auto TargetBitsLog2Const =
6468 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6469 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6472 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6474 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6482 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6483 auto TargetBitsMinusOneConst =
6484 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6486 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6487 TargetBitsMinusOneConst)
6490 FillValue = ZeroReg;
6498 for (
unsigned I = 0;
I < NumParts; ++
I) {
6500 Register InBoundsResult = FillValue;
6510 for (
unsigned K = 0; K < NumParts; ++K) {
6511 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6513 WordShift, WordShiftKConst);
6525 switch (
MI.getOpcode()) {
6526 case TargetOpcode::G_SHL:
6527 MainSrcIdx = (int)
I - (
int)K;
6528 CarrySrcIdx = MainSrcIdx - 1;
6530 case TargetOpcode::G_LSHR:
6531 case TargetOpcode::G_ASHR:
6532 MainSrcIdx = (int)
I + (
int)K;
6533 CarrySrcIdx = MainSrcIdx + 1;
6541 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6542 Register MainOp = SrcParts[MainSrcIdx];
6546 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6547 CarryOp = SrcParts[CarrySrcIdx];
6548 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6549 CarrySrcIdx >= (
int)NumParts)
6550 CarryOp = FillValue;
6556 ResultForK = FillValue;
6562 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6569 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6573 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6574 MI.eraseFromParent();
6581 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6584 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6599 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6604 "getNeutralElementForVecReduce called with invalid opcode!");
6605 case TargetOpcode::G_VECREDUCE_ADD:
6606 case TargetOpcode::G_VECREDUCE_OR:
6607 case TargetOpcode::G_VECREDUCE_XOR:
6608 case TargetOpcode::G_VECREDUCE_UMAX:
6610 case TargetOpcode::G_VECREDUCE_MUL:
6612 case TargetOpcode::G_VECREDUCE_AND:
6613 case TargetOpcode::G_VECREDUCE_UMIN:
6616 case TargetOpcode::G_VECREDUCE_SMAX:
6619 case TargetOpcode::G_VECREDUCE_SMIN:
6622 case TargetOpcode::G_VECREDUCE_FADD:
6624 case TargetOpcode::G_VECREDUCE_FMUL:
6626 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6627 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6628 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6629 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6637 unsigned Opc =
MI.getOpcode();
6639 case TargetOpcode::G_IMPLICIT_DEF:
6640 case TargetOpcode::G_LOAD: {
6648 case TargetOpcode::G_STORE:
6655 case TargetOpcode::G_AND:
6656 case TargetOpcode::G_OR:
6657 case TargetOpcode::G_XOR:
6658 case TargetOpcode::G_ADD:
6659 case TargetOpcode::G_SUB:
6660 case TargetOpcode::G_MUL:
6661 case TargetOpcode::G_FADD:
6662 case TargetOpcode::G_FSUB:
6663 case TargetOpcode::G_FMUL:
6664 case TargetOpcode::G_FDIV:
6665 case TargetOpcode::G_FCOPYSIGN:
6666 case TargetOpcode::G_UADDSAT:
6667 case TargetOpcode::G_USUBSAT:
6668 case TargetOpcode::G_SADDSAT:
6669 case TargetOpcode::G_SSUBSAT:
6670 case TargetOpcode::G_SMIN:
6671 case TargetOpcode::G_SMAX:
6672 case TargetOpcode::G_UMIN:
6673 case TargetOpcode::G_UMAX:
6674 case TargetOpcode::G_FMINNUM:
6675 case TargetOpcode::G_FMAXNUM:
6676 case TargetOpcode::G_FMINNUM_IEEE:
6677 case TargetOpcode::G_FMAXNUM_IEEE:
6678 case TargetOpcode::G_FMINIMUM:
6679 case TargetOpcode::G_FMAXIMUM:
6680 case TargetOpcode::G_FMINIMUMNUM:
6681 case TargetOpcode::G_FMAXIMUMNUM:
6682 case TargetOpcode::G_STRICT_FADD:
6683 case TargetOpcode::G_STRICT_FSUB:
6684 case TargetOpcode::G_STRICT_FMUL: {
6692 case TargetOpcode::G_SHL:
6693 case TargetOpcode::G_ASHR:
6694 case TargetOpcode::G_LSHR: {
6700 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6706 case TargetOpcode::G_FMA:
6707 case TargetOpcode::G_STRICT_FMA:
6708 case TargetOpcode::G_FSHR:
6709 case TargetOpcode::G_FSHL: {
6718 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6719 case TargetOpcode::G_EXTRACT:
6726 case TargetOpcode::G_INSERT:
6727 case TargetOpcode::G_INSERT_VECTOR_ELT:
6728 case TargetOpcode::G_FREEZE:
6729 case TargetOpcode::G_FNEG:
6730 case TargetOpcode::G_FABS:
6731 case TargetOpcode::G_FSQRT:
6732 case TargetOpcode::G_FCEIL:
6733 case TargetOpcode::G_FFLOOR:
6734 case TargetOpcode::G_FNEARBYINT:
6735 case TargetOpcode::G_FRINT:
6736 case TargetOpcode::G_INTRINSIC_ROUND:
6737 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6738 case TargetOpcode::G_INTRINSIC_TRUNC:
6739 case TargetOpcode::G_BITREVERSE:
6740 case TargetOpcode::G_BSWAP:
6741 case TargetOpcode::G_FCANONICALIZE:
6742 case TargetOpcode::G_SEXT_INREG:
6743 case TargetOpcode::G_ABS:
6744 case TargetOpcode::G_CTLZ:
6745 case TargetOpcode::G_CTPOP:
6753 case TargetOpcode::G_SELECT: {
6754 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6756 if (!CondTy.isScalar() ||
6762 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6764 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6769 if (CondTy.isVector())
6779 case TargetOpcode::G_UNMERGE_VALUES:
6781 case TargetOpcode::G_PHI:
6783 case TargetOpcode::G_SHUFFLE_VECTOR:
6785 case TargetOpcode::G_BUILD_VECTOR: {
6787 for (
auto Op :
MI.uses()) {
6795 MIRBuilder.buildDeleteTrailingVectorElements(
6796 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6797 MI.eraseFromParent();
6800 case TargetOpcode::G_SEXT:
6801 case TargetOpcode::G_ZEXT:
6802 case TargetOpcode::G_ANYEXT:
6803 case TargetOpcode::G_TRUNC:
6804 case TargetOpcode::G_FPTRUNC:
6805 case TargetOpcode::G_FPEXT:
6806 case TargetOpcode::G_FPTOSI:
6807 case TargetOpcode::G_FPTOUI:
6808 case TargetOpcode::G_FPTOSI_SAT:
6809 case TargetOpcode::G_FPTOUI_SAT:
6810 case TargetOpcode::G_SITOFP:
6811 case TargetOpcode::G_UITOFP: {
6818 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6821 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6829 case TargetOpcode::G_ICMP:
6830 case TargetOpcode::G_FCMP: {
6838 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6843 case TargetOpcode::G_BITCAST: {
6847 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6848 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6864 case TargetOpcode::G_VECREDUCE_FADD:
6865 case TargetOpcode::G_VECREDUCE_FMUL:
6866 case TargetOpcode::G_VECREDUCE_ADD:
6867 case TargetOpcode::G_VECREDUCE_MUL:
6868 case TargetOpcode::G_VECREDUCE_AND:
6869 case TargetOpcode::G_VECREDUCE_OR:
6870 case TargetOpcode::G_VECREDUCE_XOR:
6871 case TargetOpcode::G_VECREDUCE_SMAX:
6872 case TargetOpcode::G_VECREDUCE_SMIN:
6873 case TargetOpcode::G_VECREDUCE_UMAX:
6874 case TargetOpcode::G_VECREDUCE_UMIN: {
6875 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6877 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6878 auto NeutralElement = getNeutralElementForVecReduce(
6884 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6885 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6886 NeutralElement, Idx);
6890 MO.
setReg(NewVec.getReg(0));
6902 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6904 unsigned MaskNumElts = Mask.size();
6905 unsigned SrcNumElts = SrcTy.getNumElements();
6908 if (MaskNumElts == SrcNumElts)
6911 if (MaskNumElts < SrcNumElts) {
6919 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6920 MI.getOperand(1).getReg(),
6921 MI.getOperand(2).getReg(), NewMask);
6922 MI.eraseFromParent();
6927 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6928 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6937 MOps1[0] =
MI.getOperand(1).getReg();
6938 MOps2[0] =
MI.getOperand(2).getReg();
6940 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6941 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6945 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6947 if (Idx >=
static_cast<int>(SrcNumElts))
6948 Idx += PaddedMaskNumElts - SrcNumElts;
6953 if (MaskNumElts != PaddedMaskNumElts) {
6955 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6958 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6960 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6965 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6968 MI.eraseFromParent();
6974 unsigned int TypeIdx,
LLT MoreTy) {
6975 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6977 unsigned NumElts = DstTy.getNumElements();
6980 if (DstTy.isVector() && Src1Ty.isVector() &&
6981 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6989 if (DstTy != Src1Ty || DstTy != Src2Ty)
6997 for (
unsigned I = 0;
I != NumElts; ++
I) {
6999 if (Idx <
static_cast<int>(NumElts))
7002 NewMask[
I] = Idx - NumElts + WidenNumElts;
7006 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7007 MI.getOperand(1).getReg(),
7008 MI.getOperand(2).getReg(), NewMask);
7009 MI.eraseFromParent();
7018 unsigned SrcParts = Src1Regs.
size();
7019 unsigned DstParts = DstRegs.
size();
7021 unsigned DstIdx = 0;
7023 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7024 DstRegs[DstIdx] = FactorSum;
7029 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7031 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7032 i <= std::min(DstIdx, SrcParts - 1); ++i) {
7034 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7038 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7039 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7041 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7051 if (DstIdx != DstParts - 1) {
7052 MachineInstrBuilder Uaddo =
7053 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
7054 FactorSum = Uaddo.
getReg(0);
7055 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7056 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7057 MachineInstrBuilder Uaddo =
7058 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
7059 FactorSum = Uaddo.
getReg(0);
7060 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7061 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7065 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7066 for (
unsigned i = 2; i < Factors.
size(); ++i)
7067 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7070 CarrySumPrevDstIdx = CarrySum;
7071 DstRegs[DstIdx] = FactorSum;
7083 LLT DstType = MRI.getType(DstReg);
7085 if (DstType.isVector())
7088 unsigned Opcode =
MI.getOpcode();
7089 unsigned OpO, OpE, OpF;
7091 case TargetOpcode::G_SADDO:
7092 case TargetOpcode::G_SADDE:
7093 case TargetOpcode::G_UADDO:
7094 case TargetOpcode::G_UADDE:
7095 case TargetOpcode::G_ADD:
7096 OpO = TargetOpcode::G_UADDO;
7097 OpE = TargetOpcode::G_UADDE;
7098 OpF = TargetOpcode::G_UADDE;
7099 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7100 OpF = TargetOpcode::G_SADDE;
7102 case TargetOpcode::G_SSUBO:
7103 case TargetOpcode::G_SSUBE:
7104 case TargetOpcode::G_USUBO:
7105 case TargetOpcode::G_USUBE:
7106 case TargetOpcode::G_SUB:
7107 OpO = TargetOpcode::G_USUBO;
7108 OpE = TargetOpcode::G_USUBE;
7109 OpF = TargetOpcode::G_USUBE;
7110 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7111 OpF = TargetOpcode::G_SSUBE;
7118 unsigned NumDefs =
MI.getNumExplicitDefs();
7119 Register Src1 =
MI.getOperand(NumDefs).getReg();
7120 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7123 CarryDst =
MI.getOperand(1).getReg();
7124 if (
MI.getNumOperands() == NumDefs + 3)
7125 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7127 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7128 LLT LeftoverTy, DummyTy;
7130 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7135 int NarrowParts = Src1Regs.
size();
7136 Src1Regs.
append(Src1Left);
7137 Src2Regs.
append(Src2Left);
7140 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7142 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7145 if (i == e - 1 && CarryDst)
7146 CarryOut = CarryDst;
7148 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7151 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7152 {Src1Regs[i], Src2Regs[i]});
7153 }
else if (i == e - 1) {
7154 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7155 {Src1Regs[i], Src2Regs[i], CarryIn});
7157 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7158 {Src1Regs[i], Src2Regs[i], CarryIn});
7164 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7165 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7166 ArrayRef(DstRegs).drop_front(NarrowParts));
7168 MI.eraseFromParent();
7174 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7176 LLT Ty = MRI.getType(DstReg);
7180 unsigned Size = Ty.getSizeInBits();
7182 if (
Size % NarrowSize != 0)
7185 unsigned NumParts =
Size / NarrowSize;
7186 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7187 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7193 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7197 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7198 MI.eraseFromParent();
7208 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7211 LLT SrcTy = MRI.getType(Src);
7222 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7235 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7238 if (SizeOp1 % NarrowSize != 0)
7240 int NumParts = SizeOp1 / NarrowSize;
7243 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7247 uint64_t OpStart =
MI.getOperand(2).getImm();
7248 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7249 for (
int i = 0; i < NumParts; ++i) {
7250 unsigned SrcStart = i * NarrowSize;
7252 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7255 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7263 int64_t ExtractOffset;
7265 if (OpStart < SrcStart) {
7267 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7269 ExtractOffset = OpStart - SrcStart;
7270 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7274 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7276 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7277 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7284 if (MRI.getType(DstReg).isVector())
7285 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7286 else if (DstRegs.
size() > 1)
7287 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7290 MI.eraseFromParent();
7302 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7304 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7307 SrcRegs.
append(LeftoverRegs);
7311 uint64_t OpStart =
MI.getOperand(3).getImm();
7312 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7313 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7314 unsigned DstStart =
I * NarrowSize;
7316 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7324 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7326 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7330 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7338 int64_t ExtractOffset, InsertOffset;
7340 if (OpStart < DstStart) {
7342 ExtractOffset = DstStart - OpStart;
7343 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7345 InsertOffset = OpStart - DstStart;
7348 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7352 if (ExtractOffset != 0 || SegSize != OpSize) {
7354 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7355 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7358 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7359 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7367 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7370 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7372 MI.eraseFromParent();
7380 LLT DstTy = MRI.getType(DstReg);
7382 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7388 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7389 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7393 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7394 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7397 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7398 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7399 {Src0Regs[I], Src1Regs[I]});
7403 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7406 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7407 DstLeftoverRegs.
push_back(Inst.getReg(0));
7410 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7411 LeftoverTy, DstLeftoverRegs);
7413 MI.eraseFromParent();
7423 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7425 LLT DstTy = MRI.getType(DstReg);
7430 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7431 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7432 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7434 MI.eraseFromParent();
7444 Register CondReg =
MI.getOperand(1).getReg();
7445 LLT CondTy = MRI.getType(CondReg);
7450 LLT DstTy = MRI.getType(DstReg);
7456 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7457 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7461 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7462 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7465 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7467 CondReg, Src1Regs[
I], Src2Regs[
I]);
7471 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7473 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7477 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7478 LeftoverTy, DstLeftoverRegs);
7480 MI.eraseFromParent();
7490 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7493 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7494 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7497 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7499 auto C_0 =
B.buildConstant(NarrowTy, 0);
7501 UnmergeSrc.getReg(1), C_0);
7502 auto LoCTLZ = IsUndef ?
7503 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7504 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7505 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7506 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7507 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7508 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7510 MI.eraseFromParent();
7523 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7526 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7527 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7530 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7532 auto C_0 =
B.buildConstant(NarrowTy, 0);
7534 UnmergeSrc.getReg(0), C_0);
7535 auto HiCTTZ = IsUndef ?
7536 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7537 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7538 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7539 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7540 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7541 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7543 MI.eraseFromParent();
7556 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7559 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7560 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7562 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7563 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7564 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7566 MI.eraseFromParent();
7581 LLT ExpTy = MRI.getType(ExpReg);
7586 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7587 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7588 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7589 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7591 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7593 MI.getOperand(2).setReg(Trunc.getReg(0));
7600 unsigned Opc =
MI.getOpcode();
7603 auto QAction = LI.getAction(Q).Action;
7609 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7612 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7616 case TargetOpcode::G_CTLZ: {
7617 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7618 unsigned Len = SrcTy.getScalarSizeInBits();
7620 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7622 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7623 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7626 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7627 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7628 MI.eraseFromParent();
7644 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7645 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7648 Op = MIBOp.getReg(0);
7653 MI.eraseFromParent();
7656 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7659 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7663 case TargetOpcode::G_CTTZ: {
7664 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7666 unsigned Len = SrcTy.getScalarSizeInBits();
7667 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7670 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7671 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7674 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7675 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7676 MI.eraseFromParent();
7683 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7684 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7686 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7687 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7688 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7689 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7692 MI.eraseFromParent();
7696 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7697 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7701 case TargetOpcode::G_CTPOP: {
7703 LLT Ty = MRI.getType(SrcReg);
7704 unsigned Size = Ty.getScalarSizeInBits();
7716 auto C_1 =
B.buildConstant(Ty, 1);
7717 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7719 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7720 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7721 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7725 auto C_2 =
B.buildConstant(Ty, 2);
7726 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7728 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7729 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7730 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7731 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7738 auto C_4 =
B.buildConstant(Ty, 4);
7739 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7740 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7742 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7743 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7745 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7751 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7753 auto IsMulSupported = [
this](
const LLT Ty) {
7754 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7757 if (IsMulSupported(Ty)) {
7758 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7759 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7761 auto ResTmp = B8Count;
7762 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7763 auto ShiftC =
B.buildConstant(Ty, Shift);
7764 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7765 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7767 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7769 MI.eraseFromParent();
7790 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7791 LLT Ty = MRI.getType(Dst);
7792 LLT ShTy = MRI.getType(Z);
7799 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7800 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7805 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7806 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7810 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7823 MI.eraseFromParent();
7829 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7830 LLT Ty = MRI.getType(Dst);
7831 LLT ShTy = MRI.getType(Z);
7834 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7844 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7845 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7846 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7847 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7848 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7852 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7855 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7858 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7860 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7861 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7862 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7865 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7867 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7869 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7872 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7873 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7878 MI.eraseFromParent();
7889 LLT Ty = MRI.getType(Dst);
7890 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7892 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7893 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7896 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7897 return lowerFunnelShiftAsShifts(
MI);
7901 if (Result == UnableToLegalize)
7902 return lowerFunnelShiftAsShifts(
MI);
7907 auto [Dst, Src] =
MI.getFirst2Regs();
7908 LLT DstTy = MRI.getType(Dst);
7909 LLT SrcTy = MRI.getType(Src);
7913 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7921 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7925 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7929 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7934 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7935 {UnmergeSrc.getReg(0)});
7936 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7937 {UnmergeSrc.getReg(1)});
7940 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7942 MI.eraseFromParent();
7959 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7963 LLT DstTy = MRI.getType(DstReg);
7964 LLT SrcTy = MRI.getType(SrcReg);
7972 SrcTy.getElementCount().divideCoefficientBy(2));
7985 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7997 MI.eraseFromParent();
8006 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8007 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8008 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8009 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8010 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8011 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8012 MI.eraseFromParent();
8017 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8019 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8020 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8025 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8026 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8028 return lowerRotateWithReverseRotate(
MI);
8031 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8032 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8033 bool IsFShLegal =
false;
8034 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8035 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8039 MI.eraseFromParent();
8044 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8047 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8052 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8053 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8054 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8060 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8061 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8063 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8069 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8070 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8072 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8074 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8078 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
8079 MI.eraseFromParent();
8087 auto [Dst, Src] =
MI.getFirst2Regs();
8092 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8120 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8133 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8137 MI.eraseFromParent();
8145 auto [Dst, Src] =
MI.getFirst2Regs();
8150 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8163 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8165 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8170 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8172 MI.eraseFromParent();
8180 auto [Dst, Src] =
MI.getFirst2Regs();
8184 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8195 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8196 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8198 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8205 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8206 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8207 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8209 MI.eraseFromParent();
8219 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8225 MI.eraseFromParent();
8230 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8233 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8234 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8235 MIRBuilder.buildSelect(Dst, Src, True, False);
8236 MI.eraseFromParent();
8240 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8260 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8267 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8268 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8269 MIRBuilder.buildSelect(Dst, Src, True, False);
8270 MI.eraseFromParent();
8274 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8297 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8298 MI.eraseFromParent();
8306 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8310 if (SrcTy !=
S64 && SrcTy !=
S32)
8312 if (DstTy !=
S32 && DstTy !=
S64)
8339 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8341 MI.eraseFromParent();
8346 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8351 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8358 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8360 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8361 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8363 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8364 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8366 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8368 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8369 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8370 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8373 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8374 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8375 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8377 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8380 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8385 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8386 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8392 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8394 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8395 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8397 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8402 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8403 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8405 MI.eraseFromParent();
8411 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8413 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8414 unsigned SatWidth = DstTy.getScalarSizeInBits();
8418 APInt MinInt, MaxInt;
8441 if (AreExactFloatBounds) {
8443 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8445 SrcTy.changeElementSize(1), Src, MaxC);
8446 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8448 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8458 MI.eraseFromParent();
8463 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8465 DstTy.changeElementSize(1), Src, Src);
8468 MI.eraseFromParent();
8475 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8484 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8495 MI.eraseFromParent();
8501 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8503 DstTy.changeElementSize(1), Src, Src);
8505 MI.eraseFromParent();
8515 auto [Dst, Src] =
MI.getFirst2Regs();
8517 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8519 if (MRI.getType(Src).isVector())
8523 unsigned Flags =
MI.getFlags();
8526 MI.eraseFromParent();
8530 const unsigned ExpMask = 0x7ff;
8531 const unsigned ExpBiasf64 = 1023;
8532 const unsigned ExpBiasf16 = 15;
8561 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8621 MI.eraseFromParent();
8627 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8631 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8638 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8639 LLT Ty = MRI.getType(Dst);
8641 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8642 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8643 MI.eraseFromParent();
8649 case TargetOpcode::G_SMIN:
8651 case TargetOpcode::G_SMAX:
8653 case TargetOpcode::G_UMIN:
8655 case TargetOpcode::G_UMAX:
8663 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8668 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8669 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8671 MI.eraseFromParent();
8680 LLT DstTy = MRI.getType(Dst);
8681 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8691 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8692 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8694 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8697 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8698 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8699 if (TLI.preferSelectsOverBooleanArithmetic(
8702 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8703 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8705 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8706 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8712 unsigned BoolExtOp =
8714 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8715 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8719 MI.eraseFromParent();
8725 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8726 const int Src0Size = Src0Ty.getScalarSizeInBits();
8727 const int Src1Size = Src1Ty.getScalarSizeInBits();
8732 auto NotSignBitMask =
MIRBuilder.buildConstant(
8737 if (Src0Ty == Src1Ty) {
8738 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8739 }
else if (Src0Size > Src1Size) {
8740 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8741 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8742 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8743 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8745 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8746 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8747 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8748 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8754 unsigned Flags =
MI.getFlags();
8761 MI.eraseFromParent();
8772 switch (
MI.getOpcode()) {
8773 case TargetOpcode::G_FMINNUM:
8774 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8776 case TargetOpcode::G_FMINIMUMNUM:
8777 NewOp = TargetOpcode::G_FMINNUM;
8779 case TargetOpcode::G_FMAXNUM:
8780 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8782 case TargetOpcode::G_FMAXIMUMNUM:
8783 NewOp = TargetOpcode::G_FMAXNUM;
8789 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8790 LLT Ty = MRI.getType(Dst);
8800 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8803 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8808 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8809 MI.eraseFromParent();
8815 unsigned Opc =
MI.getOpcode();
8816 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8817 LLT Ty = MRI.getType(Dst);
8820 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
8822 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
8823 unsigned OpcNonIeee =
8824 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
8825 bool MinMaxMustRespectOrderedZero =
false;
8829 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
8831 MinMaxMustRespectOrderedZero =
true;
8832 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
8837 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
8845 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
8849 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
8851 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
8861 const unsigned Flags =
MI.getFlags();
8867 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
8869 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
8871 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
8873 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
8875 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
8880 MI.eraseFromParent();
8887 LLT Ty = MRI.getType(DstReg);
8888 unsigned Flags =
MI.getFlags();
8893 MI.eraseFromParent();
8899 auto [DstReg,
X] =
MI.getFirst2Regs();
8900 const unsigned Flags =
MI.getFlags();
8901 const LLT Ty = MRI.getType(DstReg);
8913 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8915 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8920 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8921 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8922 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8923 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8925 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8927 MI.eraseFromParent();
8932 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8933 unsigned Flags =
MI.getFlags();
8934 LLT Ty = MRI.getType(DstReg);
8941 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8942 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8945 SrcReg, Zero, Flags);
8947 SrcReg, Trunc, Flags);
8951 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8952 MI.eraseFromParent();
8958 const unsigned NumOps =
MI.getNumOperands();
8959 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8960 unsigned PartSize = Src0Ty.getSizeInBits();
8965 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8966 const unsigned Offset = (
I - 1) * PartSize;
8969 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8972 MRI.createGenericVirtualRegister(WideTy);
8975 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8976 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8977 ResultReg = NextResult;
8980 if (DstTy.isPointer()) {
8981 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8982 DstTy.getAddressSpace())) {
8990 MI.eraseFromParent();
8996 const unsigned NumDst =
MI.getNumOperands() - 1;
8997 Register SrcReg =
MI.getOperand(NumDst).getReg();
8998 Register Dst0Reg =
MI.getOperand(0).getReg();
8999 LLT DstTy = MRI.getType(Dst0Reg);
9008 LLT IntTy = MRI.getType(SrcReg);
9013 unsigned Offset = DstSize;
9014 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9016 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9020 MI.eraseFromParent();
9039 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9040 InsertVal =
MI.getOperand(2).getReg();
9042 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9044 LLT VecTy = MRI.getType(SrcVec);
9054 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9055 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9057 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9060 MI.eraseFromParent();
9065 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9076 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9083 int64_t
Offset = IdxVal * EltBytes;
9094 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9097 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9099 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9102 MI.eraseFromParent();
9108 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9109 MI.getFirst3RegLLTs();
9119 for (
int Idx : Mask) {
9121 if (!Undef.isValid())
9122 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
9127 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9129 int NumElts = Src0Ty.getNumElements();
9130 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9131 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9132 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9134 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9136 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9141 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9142 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9143 MI.eraseFromParent();
9149 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9150 MI.getFirst4RegLLTs();
9152 if (VecTy.isScalableVector())
9168 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9171 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9174 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9177 std::optional<APInt> PassthruSplatVal =
9180 if (PassthruSplatVal.has_value()) {
9182 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9183 }
else if (HasPassthru) {
9184 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9185 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9191 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9195 unsigned NumElmts = VecTy.getNumElements();
9196 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9198 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9201 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9204 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9209 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9211 if (HasPassthru &&
I == NumElmts - 1) {
9214 auto AllLanesSelected =
MIRBuilder.buildICmp(
9216 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9217 {OutPos, EndOfVector});
9221 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9223 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9228 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9230 MI.eraseFromParent();
9241 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9247 if (Alignment >
Align(1)) {
9250 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9259 const auto &MF = *
MI.getMF();
9265 Register AllocSize =
MI.getOperand(1).getReg();
9268 LLT PtrTy = MRI.getType(Dst);
9269 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9276 MI.eraseFromParent();
9282 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9287 MI.eraseFromParent();
9293 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9298 MI.eraseFromParent();
9304 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9305 unsigned Offset =
MI.getOperand(2).getImm();
9308 if (SrcTy.isVector()) {
9309 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9310 unsigned DstSize = DstTy.getSizeInBits();
9312 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9313 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9315 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9319 for (
unsigned Idx =
Offset / SrcEltSize;
9320 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9321 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9323 if (SubVectorElts.
size() == 1)
9324 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9326 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9328 MI.eraseFromParent();
9333 if (DstTy.isScalar() &&
9334 (SrcTy.isScalar() ||
9335 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9336 LLT SrcIntTy = SrcTy;
9337 if (!SrcTy.isScalar()) {
9339 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9346 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9350 MI.eraseFromParent();
9358 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9361 LLT DstTy = MRI.getType(Src);
9362 LLT InsertTy = MRI.getType(InsertSrc);
9370 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9372 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9376 for (; Idx <
Offset / EltSize; ++Idx) {
9377 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9382 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9383 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9385 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9394 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9397 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9398 MI.eraseFromParent();
9412 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9416 LLT IntDstTy = DstTy;
9420 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9425 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9431 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9437 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9438 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9439 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9442 MI.eraseFromParent();
9448 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9449 MI.getFirst4RegLLTs();
9450 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9453 LLT BoolTy = Dst1Ty;
9455 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9472 auto ResultLowerThanLHS =
9477 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9480 MI.eraseFromParent();
9486 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9487 const LLT Ty = MRI.getType(Res);
9490 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9491 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9492 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9503 MI.eraseFromParent();
9508 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9509 const LLT Ty = MRI.getType(Res);
9512 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9513 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9514 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9519 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9524 MI.eraseFromParent();
9530 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9531 LLT Ty = MRI.getType(Res);
9535 switch (
MI.getOpcode()) {
9538 case TargetOpcode::G_UADDSAT:
9541 BaseOp = TargetOpcode::G_ADD;
9543 case TargetOpcode::G_SADDSAT:
9546 BaseOp = TargetOpcode::G_ADD;
9548 case TargetOpcode::G_USUBSAT:
9551 BaseOp = TargetOpcode::G_SUB;
9553 case TargetOpcode::G_SSUBSAT:
9556 BaseOp = TargetOpcode::G_SUB;
9571 uint64_t NumBits = Ty.getScalarSizeInBits();
9582 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9590 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9595 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9596 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9599 MI.eraseFromParent();
9605 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9606 LLT Ty = MRI.getType(Res);
9610 unsigned OverflowOp;
9611 switch (
MI.getOpcode()) {
9614 case TargetOpcode::G_UADDSAT:
9617 OverflowOp = TargetOpcode::G_UADDO;
9619 case TargetOpcode::G_SADDSAT:
9622 OverflowOp = TargetOpcode::G_SADDO;
9624 case TargetOpcode::G_USUBSAT:
9627 OverflowOp = TargetOpcode::G_USUBO;
9629 case TargetOpcode::G_SSUBSAT:
9632 OverflowOp = TargetOpcode::G_SSUBO;
9637 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9638 Register Tmp = OverflowRes.getReg(0);
9639 Register Ov = OverflowRes.getReg(1);
9648 uint64_t NumBits = Ty.getScalarSizeInBits();
9649 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9650 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9653 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9661 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9665 MI.eraseFromParent();
9671 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9672 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9673 "Expected shlsat opcode!");
9674 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9675 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9676 LLT Ty = MRI.getType(Res);
9680 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9681 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9690 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9695 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9697 MI.eraseFromParent();
9702 auto [Dst, Src] =
MI.getFirst2Regs();
9703 const LLT Ty = MRI.getType(Src);
9704 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9705 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9708 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9709 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9710 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9711 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9714 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9716 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9717 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9718 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9720 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9721 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9722 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9724 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9725 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9726 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9728 Res.getInstr()->getOperand(0).setReg(Dst);
9730 MI.eraseFromParent();
9737 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9740 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9741 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9742 return B.buildOr(Dst,
LHS,
RHS);
9747 auto [Dst, Src] =
MI.getFirst2Regs();
9748 const LLT SrcTy = MRI.getType(Src);
9749 unsigned Size = SrcTy.getScalarSizeInBits();
9750 unsigned VSize = SrcTy.getSizeInBits();
9753 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9754 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9755 {LLT::fixed_vector(VSize / 8, 8),
9756 LLT::fixed_vector(VSize / 8, 8)}}))) {
9761 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9762 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9763 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9767 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9790 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9794 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9797 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9801 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9805 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9810 MI.eraseFromParent();
9818 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9819 int NameOpIdx = IsRead ? 1 : 0;
9820 int ValRegIndex = IsRead ? 0 : 1;
9822 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9823 const LLT Ty = MRI.getType(ValReg);
9825 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9832 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9833 Fn,
MI.getDebugLoc()));
9837 MI.eraseFromParent();
9846 MI.eraseFromParent();
9852 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9853 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9855 LLT OrigTy = MRI.getType(Result);
9859 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9860 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9862 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9864 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9865 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9868 MI.eraseFromParent();
9874 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9879 MI.eraseFromParent();
9884 MI.eraseFromParent();
9891 unsigned BitSize = SrcTy.getScalarSizeInBits();
9895 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9901 APInt ExpMask = Inf;
9907 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9908 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9909 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9910 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9911 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9913 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9917 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9919 LLT DstTyCopy = DstTy;
9921 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9949 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9952 Mask &= ~PartialCheck;
9961 else if (PartialCheck ==
fcZero)
9973 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9974 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9977 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9979 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9980 appendToRes(SubnormalRes);
9987 else if (PartialCheck ==
fcInf)
9992 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9999 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10000 if (PartialCheck ==
fcNan) {
10004 }
else if (PartialCheck ==
fcQNan) {
10014 Abs, InfWithQnanBitC);
10015 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10022 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10024 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10025 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10028 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10030 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10033 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10034 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10036 appendToRes(NormalRes);
10040 MI.eraseFromParent();
10046 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10047 MI.getFirst4RegLLTs();
10049 bool IsEltPtr = DstTy.isPointerOrPointerVector();
10053 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10054 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10058 if (MaskTy.isScalar()) {
10066 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10070 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
10072 if (DstTy.isVector()) {
10074 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
10075 MaskReg = ShufSplat.getReg(0);
10080 }
else if (!DstTy.isVector()) {
10085 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10089 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10090 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10091 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10098 MI.eraseFromParent();
10104 unsigned Opcode =
MI.getOpcode();
10107 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10108 : TargetOpcode::G_UDIV,
10109 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10111 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10112 : TargetOpcode::G_UREM,
10113 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10114 MI.eraseFromParent();
10124 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10128 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10131 MI.eraseFromParent();
10141 Register SrcReg =
MI.getOperand(1).getReg();
10142 LLT Ty = MRI.getType(SrcReg);
10143 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10146 MI.eraseFromParent();
10152 Register SrcReg =
MI.getOperand(1).getReg();
10153 Register DestReg =
MI.getOperand(0).getReg();
10155 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10156 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10159 MI.eraseFromParent();
10165 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10166 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10167 "Expected G_ABDS or G_ABDU instruction");
10169 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10170 LLT Ty = MRI.getType(LHS);
10180 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10182 MI.eraseFromParent();
10188 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10189 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10190 "Expected G_ABDS or G_ABDU instruction");
10192 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10193 LLT Ty = MRI.getType(LHS);
10198 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10199 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10200 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10202 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10203 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10205 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10207 MI.eraseFromParent();
10212 Register SrcReg =
MI.getOperand(1).getReg();
10213 Register DstReg =
MI.getOperand(0).getReg();
10215 LLT Ty = MRI.getType(DstReg);
10223 MI.eraseFromParent();
10229 Register SrcReg =
MI.getOperand(1).getReg();
10230 LLT SrcTy = MRI.getType(SrcReg);
10231 LLT DstTy = MRI.getType(SrcReg);
10234 if (SrcTy.isScalar()) {
10239 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10250 Register ListPtr =
MI.getOperand(1).getReg();
10251 LLT PtrTy = MRI.getType(ListPtr);
10258 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10260 const Align A(
MI.getOperand(2).getImm());
10262 if (
A > TLI.getMinStackArgumentAlignment()) {
10264 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10265 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10266 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10267 VAList = AndDst.getReg(0);
10274 LLT LLTTy = MRI.getType(Dst);
10277 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10278 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10283 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10285 Align EltAlignment =
DL.getABITypeAlign(Ty);
10288 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10290 MI.eraseFromParent();
10305 unsigned Limit,
const MemOp &
Op,
10306 unsigned DstAS,
unsigned SrcAS,
10307 const AttributeList &FuncAttributes,
10309 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10319 if (
Op.isFixedDstAlign())
10320 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10323 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10327 unsigned NumMemOps = 0;
10330 unsigned TySize = Ty.getSizeInBytes();
10331 while (TySize >
Size) {
10340 assert(NewTySize > 0 &&
"Could not find appropriate type");
10347 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10349 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10355 TySize = NewTySize;
10359 if (++NumMemOps > Limit)
10362 MemOps.push_back(Ty);
10372 unsigned NumBits = Ty.getScalarSizeInBits();
10374 if (!Ty.isVector() && ValVRegAndVal) {
10375 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10383 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10404 uint64_t KnownLen,
Align Alignment,
10406 auto &MF = *
MI.getParent()->getParent();
10411 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10413 bool DstAlignCanChange =
false;
10417 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10419 DstAlignCanChange =
true;
10421 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10422 std::vector<LLT> MemOps;
10424 const auto &DstMMO = **
MI.memoperands_begin();
10425 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10428 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10439 if (DstAlignCanChange) {
10442 Align NewAlign =
DL.getABITypeAlign(IRTy);
10443 if (NewAlign > Alignment) {
10444 Alignment = NewAlign;
10452 MachineIRBuilder MIB(
MI);
10454 LLT LargestTy = MemOps[0];
10455 for (
unsigned i = 1; i < MemOps.size(); i++)
10457 LargestTy = MemOps[i];
10469 LLT PtrTy = MRI.getType(Dst);
10470 unsigned DstOff = 0;
10471 unsigned Size = KnownLen;
10472 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10473 LLT Ty = MemOps[
I];
10475 if (TySize >
Size) {
10478 assert(
I == MemOps.size() - 1 &&
I != 0);
10479 DstOff -= TySize -
Size;
10489 TLI.isTruncateFree(LargestVT, VT))
10490 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10503 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10506 MIB.buildStore(
Value, Ptr, *StoreMMO);
10511 MI.eraseFromParent();
10517 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10519 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10521 const auto *MMOIt =
MI.memoperands_begin();
10523 bool IsVolatile =
MemOp->isVolatile();
10529 "inline memcpy with dynamic size is not yet supported");
10530 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10531 if (KnownLen == 0) {
10532 MI.eraseFromParent();
10536 const auto &DstMMO = **
MI.memoperands_begin();
10537 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10538 Align DstAlign = DstMMO.getBaseAlign();
10539 Align SrcAlign = SrcMMO.getBaseAlign();
10541 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10548 Align SrcAlign,
bool IsVolatile) {
10549 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10550 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10551 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10558 Align SrcAlign,
bool IsVolatile) {
10559 auto &MF = *
MI.getParent()->getParent();
10564 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10566 bool DstAlignCanChange =
false;
10568 Align Alignment = std::min(DstAlign, SrcAlign);
10572 DstAlignCanChange =
true;
10578 std::vector<LLT> MemOps;
10580 const auto &DstMMO = **
MI.memoperands_begin();
10581 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10587 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10593 if (DstAlignCanChange) {
10596 Align NewAlign =
DL.getABITypeAlign(IRTy);
10601 if (!
TRI->hasStackRealignment(MF))
10603 NewAlign = std::min(NewAlign, *StackAlign);
10605 if (NewAlign > Alignment) {
10606 Alignment = NewAlign;
10614 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10616 MachineIRBuilder MIB(
MI);
10622 unsigned CurrOffset = 0;
10623 unsigned Size = KnownLen;
10624 for (
auto CopyTy : MemOps) {
10627 if (CopyTy.getSizeInBytes() >
Size)
10628 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10639 if (CurrOffset != 0) {
10640 LLT SrcTy = MRI.getType(Src);
10643 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10645 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10649 if (CurrOffset != 0) {
10650 LLT DstTy = MRI.getType(Dst);
10651 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10653 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10654 CurrOffset += CopyTy.getSizeInBytes();
10655 Size -= CopyTy.getSizeInBytes();
10658 MI.eraseFromParent();
10664 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10666 auto &MF = *
MI.getParent()->getParent();
10671 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10673 bool DstAlignCanChange =
false;
10676 Align Alignment = std::min(DstAlign, SrcAlign);
10678 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10680 DstAlignCanChange =
true;
10682 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10683 std::vector<LLT> MemOps;
10685 const auto &DstMMO = **
MI.memoperands_begin();
10686 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10687 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10688 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10695 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10701 if (DstAlignCanChange) {
10704 Align NewAlign =
DL.getABITypeAlign(IRTy);
10709 if (!
TRI->hasStackRealignment(MF))
10710 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10711 NewAlign = std::min(NewAlign, *StackAlign);
10713 if (NewAlign > Alignment) {
10714 Alignment = NewAlign;
10722 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10724 MachineIRBuilder MIB(
MI);
10728 unsigned CurrOffset = 0;
10729 SmallVector<Register, 16> LoadVals;
10730 for (
auto CopyTy : MemOps) {
10737 if (CurrOffset != 0) {
10738 LLT SrcTy = MRI.getType(Src);
10741 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10743 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10744 CurrOffset += CopyTy.getSizeInBytes();
10748 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10749 LLT CopyTy = MemOps[
I];
10755 if (CurrOffset != 0) {
10756 LLT DstTy = MRI.getType(Dst);
10759 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10761 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10764 MI.eraseFromParent();
10770 const unsigned Opc =
MI.getOpcode();
10773 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10774 Opc == TargetOpcode::G_MEMSET) &&
10775 "Expected memcpy like instruction");
10777 auto MMOIt =
MI.memoperands_begin();
10782 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10784 if (
Opc != TargetOpcode::G_MEMSET) {
10785 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10786 MemOp = *(++MMOIt);
10787 SrcAlign =
MemOp->getBaseAlign();
10792 if (!LenVRegAndVal)
10794 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10796 if (KnownLen == 0) {
10797 MI.eraseFromParent();
10801 if (MaxLen && KnownLen > MaxLen)
10804 bool IsVolatile =
MemOp->isVolatile();
10805 if (
Opc == TargetOpcode::G_MEMCPY) {
10806 auto &MF = *
MI.getParent()->getParent();
10809 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10810 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10813 if (
Opc == TargetOpcode::G_MEMMOVE)
10814 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10815 if (
Opc == TargetOpcode::G_MEMSET)
10816 return lowerMemset(
MI, Dst, Src, KnownLen, DstAlign, IsVolatile);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static bool findGISelOptimalMemOpLowering(std::vector< LLT > &MemOps, unsigned Limit, const MemOp &Op, unsigned DstAS, unsigned SrcAS, const AttributeList &FuncAttributes, const TargetLowering &TLI)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static LegalizerHelper::LegalizeResult conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, Type *FromType, LostDebugLocObserver &LocObserver, const TargetLowering &TLI, bool IsSigned=false)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static LegalizerHelper::LegalizeResult simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver)
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static bool shouldLowerMemFuncForSize(const MachineFunction &MF)
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static LegalizerHelper::LegalizeResult createAtomicLibcall(MachineIRBuilder &MIRBuilder, MachineInstr &MI)
static RTLIB::Libcall getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI)
static std::pair< int, int > getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy)
Try to break down OrigTy into NarrowTy sized pieces.
static bool hasSameNumEltsOnAllVectorOperands(GenericMachineInstr &MI, MachineRegisterInfo &MRI, std::initializer_list< unsigned > NonVecOpIndices)
Check that all vector operands have same number of elements.
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg, LLT VecTy)
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, Type *FromType)
static void getUnmergeResults(SmallVectorImpl< Register > &Regs, const MachineInstr &MI)
Append the result registers of G_UNMERGE_VALUES MI to Regs.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
#define RTLIBCASE(LibcallPrefix)
static Type * getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Tracks DebugLocs between checkpoints and verifies that they are transferred.
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file describes how to lower LLVM code to machine code.
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmTowardZero
static const fltSemantics & IEEEdouble()
static constexpr roundingMode rmNearestTiesToEven
opStatus
IEEE-754R 7: Default exception handling.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
APInt bitcastToAPInt() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
void negate()
Negate this APInt in place.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, unsigned hiBit)
Wrap version of getBitsSet.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
LLT getLLTTy(const MachineRegisterInfo &MRI) const
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Represents a insert subvector.
Register getSubVec() const
Register getBigVec() const
uint64_t getIndexImm() const
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
Represents a threeway compare.
Register getValueReg() const
Get the stored value register.
A base class for all GenericMachineInstrs.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr ElementCount getElementCount() const
constexpr LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr LLT changeVectorElementType(LLT NewEltTy) const
Returns a vector with the same number of elements but the new element type.
constexpr LLT getScalarType() const
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
constexpr LLT changeVectorElementCount(ElementCount EC) const
Return a vector with the same element type and the new element count.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerThreewayCompare(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI)
LLVM_ABI LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI)
Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
LLVM_ABI LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty)
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSSUBE(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerSMULH_UMULH(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerLoad(GAnyLoad &MI)
LLVM_ABI LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerAbsToAddXor(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerFConstant(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerBitreverse(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
Legalize a vector instruction by increasing the number of vector elements involved and ignoring the a...
LLVM_ABI LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy)
Multi-way shift legalization: directly split wide shifts into target-sized parts in a single step,...
LLVM_ABI LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI)
LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI Register buildConstantShiftPart(unsigned Opcode, unsigned PartIdx, unsigned NumParts, ArrayRef< Register > SrcParts, const ShiftParams &Params, LLT TargetTy, LLT ShiftAmtTy)
Generates a single output part for constant shifts using direct indexing.
LLVM_ABI void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by truncating the operand's ty...
LLVM_ABI LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI, unsigned NumElts)
LLVM_ABI LegalizeResult lowerFPTOUI(MachineInstr &MI)
const TargetLowering & getTargetLowering() const
LLVM_ABI LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
LLVM_ABI LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult bitcastInsertSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_INSERT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult lowerUnmergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by replacing the value type.
LLVM_ABI LegalizeResult scalarizeVectorBooleanStore(GStore &MI)
Given a store of a boolean vector, scalarize it.
LLVM_ABI LegalizeResult lowerBitcast(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerReadWriteRegister(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, LLT HalfTy, LLT ShiftAmtTy)
LLVM_ABI LegalizeResult lowerISFPCLASS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFAbs(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerVectorReduction(MachineInstr &MI)
const LegalizerInfo & getLegalizerInfo() const
Expose LegalizerInfo so the clients can re-use.
LLVM_ABI LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult fewerElementsVectorMultiEltType(GenericMachineInstr &MI, unsigned NumElts, std::initializer_list< unsigned > NonVecOpIndices={})
Handles most opcodes.
LLVM_ABI LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarShiftByConstantMultiway(MachineInstr &MI, const APInt &Amt, LLT TargetTy, LLT ShiftAmtTy)
Optimized path for constant shift amounts using static indexing.
LLVM_ABI MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val)
Create a store of Val to a stack temporary and return a load as the same type as Res.
LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ AlreadyLegal
Instruction was already legal and no change was made to the MachineFunction.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFCopySign(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B)
LLVM_ABI LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSADDE(MachineInstr &MI)
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
LLVM_ABI LegalizeResult lowerFunnelShift(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFPTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
LLVM_ABI LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
LLVM_ABI LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerFFloor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult fewerElementsVectorSeqReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize, Align Alignment, LLT PtrTy)
LLVM_ABI LegalizeResult lowerFPTOSI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerUITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerShuffleVector(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerMergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerVECTOR_COMPRESS(MachineInstr &MI)
LLVM_ABI void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by producing a vector with und...
LLVM_ABI LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF32WithSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0)
LLVM_ABI Register coerceToScalar(Register Val)
Cast the given value to an LLT::scalar with an equivalent size.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI LegalizeResult lowerTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBswap(MachineInstr &MI)
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
LLVM_ABI LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const
Return the alignment to use for a stack temporary object with the given type.
LLVM_ABI LegalizeResult lowerConstant(MachineInstr &MI)
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LLVM_ABI LegalizeResult legalizeInstrStep(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Replace MI by a sequence of legal instructions that can implement the same operation.
LLVM_ABI LegalizeResult lowerFMinimumMaximum(MachineInstr &MI)
TypeSize getValue() const
void checkpoint(bool CheckDebugLocs=true)
Call this to indicate that it's a good point to assess whether locations have been lost.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
LLVM_ABI StringRef getString() const
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
LLVM_ABI iterator getFirstTerminatorForward()
Finds the first terminator in a block by scanning forward.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_UREM Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0)
Build and insert integer negation Zero = G_CONSTANT 0 Res = G_SUB Zero, Op0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_UITOFP Src0.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
MachineInstrBuilder buildXor(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_XOR Op0, Op1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
virtual bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *=nullptr) const
Determine if the target supports unaligned memory accesses.
virtual LLT getOptimalMemOpLLT(const MemOp &Op, const AttributeList &) const
LLT returning variant.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const
Returns true if arguments should be sign-extended in lib calls.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
const Triple & getTargetTriple() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const CallLowering * getCallLowering() const
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, DriverKit, XROS, or bridgeOS).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Type * getType() const
All values are typed, get the type of this value.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ Custom
The target wants to do something special with this combination of operand and type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
FunctionAddr VTableAddr Value
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
LLVM_ABI LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver)
Create a libcall to memcpy et al.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI LegalizerHelper::LegalizeResult createLibcall(MachineIRBuilder &MIRBuilder, const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr)
Helper function that creates a libcall to the given Name using the given calling convention CC.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isKnownNeverNaN(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the floating-point scalar value is not a NaN or if the floating-point vector value has...
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI)
Returns true if Val can be assumed to never be a signaling NaN.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
bool isKnownNeverZero() const
Return true if it's known this can never be a zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
static MemOp Set(uint64_t Size, bool DstAlignCanChange, Align DstAlign, bool IsZeroMemset, bool IsVolatile)
static MemOp Copy(uint64_t Size, bool DstAlignCanChange, Align DstAlign, Align SrcAlign, bool IsVolatile, bool MemcpyStrSrc=false)