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()) {
129 auto Step = LI.getAction(
MI, MRI);
130 switch (Step.Action) {
145 return bitcast(
MI, Step.TypeIdx, Step.NewType);
148 return lower(
MI, Step.TypeIdx, Step.NewType);
157 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
165void LegalizerHelper::insertParts(
Register DstReg,
187 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
189 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
190 return mergeMixedSubvectors(DstReg, AllRegs);
196 extractGCDType(GCDRegs, GCDTy, PartReg);
197 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
198 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
203 LLT Ty = MRI.getType(
Reg);
211void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
214 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
215 appendVectorElts(AllElts, PartRegs[i]);
218 if (!MRI.getType(Leftover).isVector())
221 appendVectorElts(AllElts, Leftover);
223 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
229 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
231 const int StartIdx = Regs.
size();
232 const int NumResults =
MI.getNumOperands() - 1;
234 for (
int I = 0;
I != NumResults; ++
I)
235 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
240 LLT SrcTy = MRI.getType(SrcReg);
241 if (SrcTy == GCDTy) {
247 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
254 LLT SrcTy = MRI.getType(SrcReg);
256 extractGCDType(Parts, GCDTy, SrcReg);
260LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
262 unsigned PadStrategy) {
267 int NumOrigSrc = VRegs.
size();
273 if (NumOrigSrc < NumParts * NumSubParts) {
274 if (PadStrategy == TargetOpcode::G_ZEXT)
275 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
276 else if (PadStrategy == TargetOpcode::G_ANYEXT)
277 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
279 assert(PadStrategy == TargetOpcode::G_SEXT);
284 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
300 for (
int I = 0;
I != NumParts; ++
I) {
301 bool AllMergePartsArePadding =
true;
304 for (
int J = 0; J != NumSubParts; ++J) {
305 int Idx =
I * NumSubParts + J;
306 if (Idx >= NumOrigSrc) {
307 SubMerge[J] = PadReg;
311 SubMerge[J] = VRegs[Idx];
314 AllMergePartsArePadding =
false;
320 if (AllMergePartsArePadding && !AllPadReg) {
321 if (PadStrategy == TargetOpcode::G_ANYEXT)
322 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
323 else if (PadStrategy == TargetOpcode::G_ZEXT)
324 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
333 Remerge[
I] = AllPadReg;
337 if (NumSubParts == 1)
338 Remerge[
I] = SubMerge[0];
340 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
343 if (AllMergePartsArePadding && !AllPadReg)
344 AllPadReg = Remerge[
I];
347 VRegs = std::move(Remerge);
351void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
353 LLT DstTy = MRI.getType(DstReg);
358 if (DstTy == LCMTy) {
359 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
363 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
372 UnmergeDefs[0] = DstReg;
373 for (
unsigned I = 1;
I != NumDefs; ++
I)
374 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
377 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
385#define RTLIBCASE_INT(LibcallPrefix) \
389 return RTLIB::LibcallPrefix##32; \
391 return RTLIB::LibcallPrefix##64; \
393 return RTLIB::LibcallPrefix##128; \
395 llvm_unreachable("unexpected size"); \
399#define RTLIBCASE(LibcallPrefix) \
403 return RTLIB::LibcallPrefix##32; \
405 return RTLIB::LibcallPrefix##64; \
407 return RTLIB::LibcallPrefix##80; \
409 return RTLIB::LibcallPrefix##128; \
411 llvm_unreachable("unexpected size"); \
416 case TargetOpcode::G_LROUND:
418 case TargetOpcode::G_LLROUND:
420 case TargetOpcode::G_MUL:
422 case TargetOpcode::G_SDIV:
424 case TargetOpcode::G_UDIV:
426 case TargetOpcode::G_SREM:
428 case TargetOpcode::G_UREM:
430 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
432 case TargetOpcode::G_FADD:
434 case TargetOpcode::G_FSUB:
436 case TargetOpcode::G_FMUL:
438 case TargetOpcode::G_FDIV:
440 case TargetOpcode::G_FEXP:
442 case TargetOpcode::G_FEXP2:
444 case TargetOpcode::G_FEXP10:
446 case TargetOpcode::G_FREM:
448 case TargetOpcode::G_FPOW:
450 case TargetOpcode::G_FPOWI:
452 case TargetOpcode::G_FMA:
454 case TargetOpcode::G_FSIN:
456 case TargetOpcode::G_FCOS:
458 case TargetOpcode::G_FTAN:
460 case TargetOpcode::G_FASIN:
462 case TargetOpcode::G_FACOS:
464 case TargetOpcode::G_FATAN:
466 case TargetOpcode::G_FATAN2:
468 case TargetOpcode::G_FSINH:
470 case TargetOpcode::G_FCOSH:
472 case TargetOpcode::G_FTANH:
474 case TargetOpcode::G_FSINCOS:
476 case TargetOpcode::G_FMODF:
478 case TargetOpcode::G_FLOG10:
480 case TargetOpcode::G_FLOG:
482 case TargetOpcode::G_FLOG2:
484 case TargetOpcode::G_FLDEXP:
486 case TargetOpcode::G_FCEIL:
488 case TargetOpcode::G_FFLOOR:
490 case TargetOpcode::G_FMINNUM:
492 case TargetOpcode::G_FMAXNUM:
494 case TargetOpcode::G_FMINIMUMNUM:
496 case TargetOpcode::G_FMAXIMUMNUM:
498 case TargetOpcode::G_FSQRT:
500 case TargetOpcode::G_FRINT:
502 case TargetOpcode::G_FNEARBYINT:
504 case TargetOpcode::G_INTRINSIC_TRUNC:
506 case TargetOpcode::G_INTRINSIC_ROUND:
508 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
510 case TargetOpcode::G_INTRINSIC_LRINT:
512 case TargetOpcode::G_INTRINSIC_LLRINT:
532 AttributeList CallerAttrs =
F.getAttributes();
533 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
534 .removeAttribute(Attribute::NoAlias)
535 .removeAttribute(Attribute::NonNull)
540 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
541 CallerAttrs.hasRetAttr(Attribute::SExt))
552 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
559 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
567 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
570 if (Ret->getNumImplicitOperands() != 1)
573 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
590 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
595 Info.OrigRet = Result;
598 (Result.Ty->isVoidTy() ||
599 Result.Ty ==
MIRBuilder.getMF().getFunction().getReturnType()) &&
607 if (
MI && Info.LoweredTailCall) {
608 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
618 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
619 "Expected instr following MI to be return or debug inst?");
622 Next->eraseFromParent();
623 }
while (
MI->getNextNode());
638 RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(
Libcall);
639 if (LibcallImpl == RTLIB::Unsupported)
642 auto &TLI = *
MIRBuilder.getMF().getSubtarget().getTargetLowering();
659 Args.push_back({MO.getReg(), OpType, 0});
673 LLT DstTy =
MRI.getType(DstSin);
678 unsigned AddrSpace =
DL.getAllocaAddrSpace();
696 if (LibcallResult != LegalizeResult::Legalized)
704 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
705 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
706 MI.eraseFromParent();
721 LLT DstTy = MRI.getType(DstFrac);
726 unsigned AddrSpace =
DL.getAllocaAddrSpace();
727 MachinePointerInfo PtrInfo;
736 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
739 if (LibcallResult != LegalizeResult::Legalized)
745 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
746 MI.eraseFromParent();
757 case TargetOpcode::G_FPEXT:
759 case TargetOpcode::G_FPTRUNC:
761 case TargetOpcode::G_FPTOSI:
763 case TargetOpcode::G_FPTOUI:
765 case TargetOpcode::G_SITOFP:
767 case TargetOpcode::G_UITOFP:
777 if (FromType->isIntegerTy()) {
778 if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
779 Arg.
Flags[0].setSExt();
781 Arg.
Flags[0].setZExt();
792 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
796 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
800 LLT OpLLT = MRI.getType(Reg);
801 Type *OpTy =
nullptr;
806 Args.push_back({Reg, OpTy, 0});
809 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
810 auto &TLI = *
MIRBuilder.getMF().getSubtarget().getTargetLowering();
811 RTLIB::Libcall RTLibcall;
812 unsigned Opc =
MI.getOpcode();
815 case TargetOpcode::G_BZERO:
816 RTLibcall = RTLIB::BZERO;
817 Name = TLI.getLibcallName(RTLibcall);
819 case TargetOpcode::G_MEMCPY:
820 RTLibcall = RTLIB::MEMCPY;
821 Name = TLI.getLibcallImplName(TLI.getMemcpyImpl()).data();
822 Args[0].Flags[0].setReturned();
824 case TargetOpcode::G_MEMMOVE:
825 RTLibcall = RTLIB::MEMMOVE;
826 Name = TLI.getLibcallName(RTLibcall);
827 Args[0].Flags[0].setReturned();
829 case TargetOpcode::G_MEMSET:
830 RTLibcall = RTLIB::MEMSET;
831 Name = TLI.getLibcallName(RTLibcall);
832 Args[0].Flags[0].setReturned();
846 Info.
CallConv = TLI.getLibcallCallingConv(RTLibcall);
850 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
857 if (Info.LoweredTailCall) {
858 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
868 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
869 "Expected instr following MI to be return or debug inst?");
872 Next->eraseFromParent();
873 }
while (
MI.getNextNode());
883 unsigned Opc =
MI.getOpcode();
885 auto &MMO = AtomicMI.getMMO();
886 auto Ordering = MMO.getMergedOrdering();
887 LLT MemType = MMO.getMemoryType();
890 return RTLIB::UNKNOWN_LIBCALL;
892#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
894 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
896 case TargetOpcode::G_ATOMIC_CMPXCHG:
897 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
898 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
899 return getOutlineAtomicHelper(LC, Ordering, MemSize);
901 case TargetOpcode::G_ATOMICRMW_XCHG: {
902 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
903 return getOutlineAtomicHelper(LC, Ordering, MemSize);
905 case TargetOpcode::G_ATOMICRMW_ADD:
906 case TargetOpcode::G_ATOMICRMW_SUB: {
907 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
908 return getOutlineAtomicHelper(LC, Ordering, MemSize);
910 case TargetOpcode::G_ATOMICRMW_AND: {
911 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
912 return getOutlineAtomicHelper(LC, Ordering, MemSize);
914 case TargetOpcode::G_ATOMICRMW_OR: {
915 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
916 return getOutlineAtomicHelper(LC, Ordering, MemSize);
918 case TargetOpcode::G_ATOMICRMW_XOR: {
919 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
920 return getOutlineAtomicHelper(LC, Ordering, MemSize);
923 return RTLIB::UNKNOWN_LIBCALL;
936 unsigned Opc =
MI.getOpcode();
938 case TargetOpcode::G_ATOMIC_CMPXCHG:
939 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
942 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
943 MI.getFirst4RegLLTs();
946 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
947 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
948 NewLLT) =
MI.getFirst5RegLLTs();
958 case TargetOpcode::G_ATOMICRMW_XCHG:
959 case TargetOpcode::G_ATOMICRMW_ADD:
960 case TargetOpcode::G_ATOMICRMW_SUB:
961 case TargetOpcode::G_ATOMICRMW_AND:
962 case TargetOpcode::G_ATOMICRMW_OR:
963 case TargetOpcode::G_ATOMICRMW_XOR: {
964 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
967 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
971 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
986 const char *Name = TLI.getLibcallName(RTLibcall);
996 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
1001 if (!CLI.lowerCall(MIRBuilder,
Info))
1007static RTLIB::Libcall
1009 RTLIB::Libcall RTLibcall;
1010 switch (
MI.getOpcode()) {
1011 case TargetOpcode::G_GET_FPENV:
1012 RTLibcall = RTLIB::FEGETENV;
1014 case TargetOpcode::G_SET_FPENV:
1015 case TargetOpcode::G_RESET_FPENV:
1016 RTLibcall = RTLIB::FESETENV;
1018 case TargetOpcode::G_GET_FPMODE:
1019 RTLibcall = RTLIB::FEGETMODE;
1021 case TargetOpcode::G_SET_FPMODE:
1022 case TargetOpcode::G_RESET_FPMODE:
1023 RTLibcall = RTLIB::FESETMODE;
1055 LLT StateTy = MRI.getType(Dst);
1058 MachinePointerInfo TempPtrInfo;
1062 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1067 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
1075 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"); \
1160 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1163 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1170 LLT DstTy = MRI.getType(DstReg);
1171 const auto Cond =
Cmp->getCond();
1176 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1181 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1185 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1192 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1198 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1200 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1213 const auto [OeqLibcall, OeqPred] =
1215 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1217 const auto [UnoLibcall, UnoPred] =
1219 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1234 const auto [OeqLibcall, OeqPred] =
1239 const auto [UnoLibcall, UnoPred] =
1244 if (NotOeq && NotUno)
1263 const auto [InversedLibcall, InversedPred] =
1265 if (!BuildLibcall(InversedLibcall,
1290 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1292 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1295 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1301 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1306 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1308 switch (
MI.getOpcode()) {
1311 case TargetOpcode::G_MUL:
1312 case TargetOpcode::G_SDIV:
1313 case TargetOpcode::G_UDIV:
1314 case TargetOpcode::G_SREM:
1315 case TargetOpcode::G_UREM:
1316 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1317 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1325 case TargetOpcode::G_FADD:
1326 case TargetOpcode::G_FSUB:
1327 case TargetOpcode::G_FMUL:
1328 case TargetOpcode::G_FDIV:
1329 case TargetOpcode::G_FMA:
1330 case TargetOpcode::G_FPOW:
1331 case TargetOpcode::G_FREM:
1332 case TargetOpcode::G_FCOS:
1333 case TargetOpcode::G_FSIN:
1334 case TargetOpcode::G_FTAN:
1335 case TargetOpcode::G_FACOS:
1336 case TargetOpcode::G_FASIN:
1337 case TargetOpcode::G_FATAN:
1338 case TargetOpcode::G_FATAN2:
1339 case TargetOpcode::G_FCOSH:
1340 case TargetOpcode::G_FSINH:
1341 case TargetOpcode::G_FTANH:
1342 case TargetOpcode::G_FLOG10:
1343 case TargetOpcode::G_FLOG:
1344 case TargetOpcode::G_FLOG2:
1345 case TargetOpcode::G_FEXP:
1346 case TargetOpcode::G_FEXP2:
1347 case TargetOpcode::G_FEXP10:
1348 case TargetOpcode::G_FCEIL:
1349 case TargetOpcode::G_FFLOOR:
1350 case TargetOpcode::G_FMINNUM:
1351 case TargetOpcode::G_FMAXNUM:
1352 case TargetOpcode::G_FMINIMUMNUM:
1353 case TargetOpcode::G_FMAXIMUMNUM:
1354 case TargetOpcode::G_FSQRT:
1355 case TargetOpcode::G_FRINT:
1356 case TargetOpcode::G_FNEARBYINT:
1357 case TargetOpcode::G_INTRINSIC_TRUNC:
1358 case TargetOpcode::G_INTRINSIC_ROUND:
1359 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1360 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1364 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1372 case TargetOpcode::G_FSINCOS: {
1373 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1377 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1382 case TargetOpcode::G_FMODF: {
1383 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1387 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1392 case TargetOpcode::G_LROUND:
1393 case TargetOpcode::G_LLROUND:
1394 case TargetOpcode::G_INTRINSIC_LRINT:
1395 case TargetOpcode::G_INTRINSIC_LLRINT: {
1396 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1400 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1402 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1408 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1411 MI.eraseFromParent();
1414 case TargetOpcode::G_FPOWI:
1415 case TargetOpcode::G_FLDEXP: {
1416 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1420 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1422 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1427 {
MI.getOperand(1).getReg(), HLTy, 0},
1428 {
MI.getOperand(2).getReg(), ITy, 1}};
1429 Args[1].Flags[0].setSExt();
1431 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1436 case TargetOpcode::G_FPEXT:
1437 case TargetOpcode::G_FPTRUNC: {
1440 if (!FromTy || !ToTy)
1447 case TargetOpcode::G_FCMP: {
1451 MI.eraseFromParent();
1454 case TargetOpcode::G_FPTOSI:
1455 case TargetOpcode::G_FPTOUI: {
1459 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1460 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1463 FromTy, LocObserver);
1468 case TargetOpcode::G_SITOFP:
1469 case TargetOpcode::G_UITOFP: {
1470 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1473 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1475 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1482 case TargetOpcode::G_ATOMICRMW_XCHG:
1483 case TargetOpcode::G_ATOMICRMW_ADD:
1484 case TargetOpcode::G_ATOMICRMW_SUB:
1485 case TargetOpcode::G_ATOMICRMW_AND:
1486 case TargetOpcode::G_ATOMICRMW_OR:
1487 case TargetOpcode::G_ATOMICRMW_XOR:
1488 case TargetOpcode::G_ATOMIC_CMPXCHG:
1489 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1495 case TargetOpcode::G_BZERO:
1496 case TargetOpcode::G_MEMCPY:
1497 case TargetOpcode::G_MEMMOVE:
1498 case TargetOpcode::G_MEMSET: {
1503 MI.eraseFromParent();
1506 case TargetOpcode::G_GET_FPENV:
1507 case TargetOpcode::G_GET_FPMODE: {
1513 case TargetOpcode::G_SET_FPENV:
1514 case TargetOpcode::G_SET_FPMODE: {
1520 case TargetOpcode::G_RESET_FPENV:
1521 case TargetOpcode::G_RESET_FPMODE: {
1529 MI.eraseFromParent();
1536 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1539 switch (
MI.getOpcode()) {
1542 case TargetOpcode::G_IMPLICIT_DEF: {
1544 LLT DstTy = MRI.getType(DstReg);
1552 if (SizeOp0 % NarrowSize != 0) {
1557 MI.eraseFromParent();
1561 int NumParts = SizeOp0 / NarrowSize;
1564 for (
int i = 0; i < NumParts; ++i)
1568 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1570 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1571 MI.eraseFromParent();
1574 case TargetOpcode::G_CONSTANT: {
1575 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1576 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1577 unsigned TotalSize = Ty.getSizeInBits();
1579 int NumParts = TotalSize / NarrowSize;
1582 for (
int I = 0;
I != NumParts; ++
I) {
1583 unsigned Offset =
I * NarrowSize;
1590 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1592 if (LeftoverBits != 0) {
1596 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1600 insertParts(
MI.getOperand(0).getReg(),
1601 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1603 MI.eraseFromParent();
1606 case TargetOpcode::G_SEXT:
1607 case TargetOpcode::G_ZEXT:
1608 case TargetOpcode::G_ANYEXT:
1610 case TargetOpcode::G_TRUNC: {
1614 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1616 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1620 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1621 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1622 MI.eraseFromParent();
1625 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1626 case TargetOpcode::G_FREEZE: {
1630 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1635 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1637 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1639 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1643 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1644 MI.eraseFromParent();
1647 case TargetOpcode::G_ADD:
1648 case TargetOpcode::G_SUB:
1649 case TargetOpcode::G_SADDO:
1650 case TargetOpcode::G_SSUBO:
1651 case TargetOpcode::G_SADDE:
1652 case TargetOpcode::G_SSUBE:
1653 case TargetOpcode::G_UADDO:
1654 case TargetOpcode::G_USUBO:
1655 case TargetOpcode::G_UADDE:
1656 case TargetOpcode::G_USUBE:
1658 case TargetOpcode::G_MUL:
1659 case TargetOpcode::G_UMULH:
1661 case TargetOpcode::G_EXTRACT:
1663 case TargetOpcode::G_INSERT:
1665 case TargetOpcode::G_LOAD: {
1667 Register DstReg = LoadMI.getDstReg();
1668 LLT DstTy = MRI.getType(DstReg);
1672 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1673 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1674 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1676 LoadMI.eraseFromParent();
1682 case TargetOpcode::G_ZEXTLOAD:
1683 case TargetOpcode::G_SEXTLOAD: {
1685 Register DstReg = LoadMI.getDstReg();
1686 Register PtrReg = LoadMI.getPointerReg();
1688 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1689 auto &MMO = LoadMI.getMMO();
1692 if (MemSize == NarrowSize) {
1694 }
else if (MemSize < NarrowSize) {
1695 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1696 }
else if (MemSize > NarrowSize) {
1706 LoadMI.eraseFromParent();
1709 case TargetOpcode::G_STORE: {
1712 Register SrcReg = StoreMI.getValueReg();
1713 LLT SrcTy = MRI.getType(SrcReg);
1714 if (SrcTy.isVector())
1717 int NumParts = SizeOp0 / NarrowSize;
1719 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1720 if (SrcTy.isVector() && LeftoverBits != 0)
1723 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1724 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1726 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1727 StoreMI.eraseFromParent();
1733 case TargetOpcode::G_SELECT:
1735 case TargetOpcode::G_AND:
1736 case TargetOpcode::G_OR:
1737 case TargetOpcode::G_XOR: {
1749 case TargetOpcode::G_SHL:
1750 case TargetOpcode::G_LSHR:
1751 case TargetOpcode::G_ASHR:
1753 case TargetOpcode::G_CTLZ:
1754 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1755 case TargetOpcode::G_CTTZ:
1756 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1757 case TargetOpcode::G_CTLS:
1758 case TargetOpcode::G_CTPOP:
1760 switch (
MI.getOpcode()) {
1761 case TargetOpcode::G_CTLZ:
1762 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1764 case TargetOpcode::G_CTTZ:
1765 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1767 case TargetOpcode::G_CTPOP:
1769 case TargetOpcode::G_CTLS:
1779 case TargetOpcode::G_INTTOPTR:
1787 case TargetOpcode::G_PTRTOINT:
1795 case TargetOpcode::G_PHI: {
1798 if (SizeOp0 % NarrowSize != 0)
1801 unsigned NumParts = SizeOp0 / NarrowSize;
1805 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1813 for (
unsigned i = 0; i < NumParts; ++i) {
1814 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1816 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1817 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1818 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1821 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1823 MI.eraseFromParent();
1826 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1827 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1831 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1837 case TargetOpcode::G_ICMP: {
1839 LLT SrcTy = MRI.getType(LHS);
1845 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1851 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1852 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1858 LLT ResTy = MRI.getType(Dst);
1863 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1865 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1866 auto LHS = std::get<0>(LHSAndRHS);
1867 auto RHS = std::get<1>(LHSAndRHS);
1868 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1875 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1876 auto LHS = std::get<0>(LHSAndRHS);
1877 auto RHS = std::get<1>(LHSAndRHS);
1878 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1879 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1880 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1881 TargetOpcode::G_ZEXT);
1888 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1889 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1890 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1895 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1899 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1904 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1908 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1911 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1914 LHSPartRegs[
I], RHSPartRegs[
I]);
1915 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1921 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1930 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1934 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1935 RHSLeftoverRegs[
I]);
1937 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1938 RHSLeftoverRegs[
I]);
1941 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1942 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1948 MI.eraseFromParent();
1951 case TargetOpcode::G_FCMP:
1960 case TargetOpcode::G_SEXT_INREG: {
1964 int64_t SizeInBits =
MI.getOperand(2).getImm();
1973 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
1974 MO1.
setReg(TruncMIB.getReg(0));
1977 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
1989 if (SizeOp0 % NarrowSize != 0)
1991 int NumParts = SizeOp0 / NarrowSize;
1999 for (
int i = 0; i < NumParts; ++i) {
2000 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2015 for (
int i = 0; i < NumParts; ++i) {
2018 PartialExtensionReg = DstRegs.
back();
2020 assert(PartialExtensionReg &&
2021 "Expected to visit partial extension before full");
2022 if (FullExtensionReg) {
2027 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2029 FullExtensionReg = DstRegs.
back();
2034 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2037 PartialExtensionReg = DstRegs.
back();
2043 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2044 MI.eraseFromParent();
2047 case TargetOpcode::G_BSWAP:
2048 case TargetOpcode::G_BITREVERSE: {
2049 if (SizeOp0 % NarrowSize != 0)
2054 unsigned NumParts = SizeOp0 / NarrowSize;
2055 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2058 for (
unsigned i = 0; i < NumParts; ++i) {
2059 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2060 {SrcRegs[NumParts - 1 - i]});
2064 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2067 MI.eraseFromParent();
2070 case TargetOpcode::G_PTR_ADD:
2071 case TargetOpcode::G_PTRMASK: {
2079 case TargetOpcode::G_FPTOUI:
2080 case TargetOpcode::G_FPTOSI:
2081 case TargetOpcode::G_FPTOUI_SAT:
2082 case TargetOpcode::G_FPTOSI_SAT:
2084 case TargetOpcode::G_FPEXT:
2091 case TargetOpcode::G_FLDEXP:
2092 case TargetOpcode::G_STRICT_FLDEXP:
2094 case TargetOpcode::G_VSCALE: {
2096 LLT Ty = MRI.getType(Dst);
2100 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2101 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2102 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2105 MI.eraseFromParent();
2112 LLT Ty = MRI.getType(Val);
2118 if (Ty.isPointer()) {
2119 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2121 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2127 if (Ty.isPointerVector())
2128 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2129 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2133 unsigned OpIdx,
unsigned ExtOpcode) {
2135 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2136 MO.
setReg(ExtB.getReg(0));
2142 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2143 MO.
setReg(ExtB.getReg(0));
2147 unsigned OpIdx,
unsigned TruncOpcode) {
2149 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2151 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2156 unsigned OpIdx,
unsigned ExtOpcode) {
2158 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2160 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2169 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2171 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2177 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2187 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2194LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2199 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2200 if (DstTy.isVector())
2203 LLT SrcTy =
MRI.getType(Src1Reg);
2204 const int DstSize = DstTy.getSizeInBits();
2205 const int SrcSize = SrcTy.getSizeInBits();
2207 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2209 unsigned NumOps =
MI.getNumOperands();
2210 unsigned NumSrc =
MI.getNumOperands() - 1;
2211 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2213 if (WideSize >= DstSize) {
2217 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2218 const unsigned Offset = (
I - 1) * PartSize;
2226 MRI.createGenericVirtualRegister(WideTy);
2231 ResultReg = NextResult;
2234 if (WideSize > DstSize)
2236 else if (DstTy.isPointer())
2239 MI.eraseFromParent();
2264 const int GCD = std::gcd(SrcSize, WideSize);
2274 if (GCD == SrcSize) {
2277 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2278 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2284 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2286 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2290 const int PartsPerGCD = WideSize / GCD;
2294 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2296 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2303 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2305 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2306 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2309 MI.eraseFromParent();
2314LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2319 int NumDst =
MI.getNumOperands() - 1;
2320 Register SrcReg =
MI.getOperand(NumDst).getReg();
2321 LLT SrcTy = MRI.getType(SrcReg);
2325 Register Dst0Reg =
MI.getOperand(0).getReg();
2326 LLT DstTy = MRI.getType(Dst0Reg);
2335 dbgs() <<
"Not casting non-integral address space integer\n");
2340 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2348 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2356 for (
int I = 1;
I != NumDst; ++
I) {
2357 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2358 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2362 MI.eraseFromParent();
2373 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2377 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2380 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2398 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2403 if (PartsPerRemerge == 1) {
2406 for (
int I = 0;
I != NumUnmerge; ++
I) {
2407 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2409 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2410 int Idx =
I * PartsPerUnmerge + J;
2412 MIB.addDef(
MI.getOperand(Idx).getReg());
2415 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2419 MIB.addUse(Unmerge.getReg(
I));
2422 SmallVector<Register, 16> Parts;
2423 for (
int J = 0; J != NumUnmerge; ++J)
2424 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2427 for (
int I = 0;
I != NumDst; ++
I) {
2428 for (
int J = 0; J < PartsPerRemerge; ++J) {
2429 const int Idx =
I * PartsPerRemerge + J;
2433 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2434 RemergeParts.
clear();
2438 MI.eraseFromParent();
2443LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2445 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2446 unsigned Offset =
MI.getOperand(2).getImm();
2449 if (SrcTy.
isVector() || DstTy.isVector())
2461 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2465 if (DstTy.isPointer())
2472 MI.eraseFromParent();
2477 LLT ShiftTy = SrcTy;
2486 MI.eraseFromParent();
2517LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2519 if (TypeIdx != 0 || WideTy.
isVector())
2529LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2533 std::optional<Register> CarryIn;
2534 switch (
MI.getOpcode()) {
2537 case TargetOpcode::G_SADDO:
2538 Opcode = TargetOpcode::G_ADD;
2539 ExtOpcode = TargetOpcode::G_SEXT;
2541 case TargetOpcode::G_SSUBO:
2542 Opcode = TargetOpcode::G_SUB;
2543 ExtOpcode = TargetOpcode::G_SEXT;
2545 case TargetOpcode::G_UADDO:
2546 Opcode = TargetOpcode::G_ADD;
2547 ExtOpcode = TargetOpcode::G_ZEXT;
2549 case TargetOpcode::G_USUBO:
2550 Opcode = TargetOpcode::G_SUB;
2551 ExtOpcode = TargetOpcode::G_ZEXT;
2553 case TargetOpcode::G_SADDE:
2554 Opcode = TargetOpcode::G_UADDE;
2555 ExtOpcode = TargetOpcode::G_SEXT;
2556 CarryIn =
MI.getOperand(4).getReg();
2558 case TargetOpcode::G_SSUBE:
2559 Opcode = TargetOpcode::G_USUBE;
2560 ExtOpcode = TargetOpcode::G_SEXT;
2561 CarryIn =
MI.getOperand(4).getReg();
2563 case TargetOpcode::G_UADDE:
2564 Opcode = TargetOpcode::G_UADDE;
2565 ExtOpcode = TargetOpcode::G_ZEXT;
2566 CarryIn =
MI.getOperand(4).getReg();
2568 case TargetOpcode::G_USUBE:
2569 Opcode = TargetOpcode::G_USUBE;
2570 ExtOpcode = TargetOpcode::G_ZEXT;
2571 CarryIn =
MI.getOperand(4).getReg();
2587 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2588 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2592 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2594 .buildInstr(Opcode, {WideTy, CarryOutTy},
2595 {LHSExt, RHSExt, *CarryIn})
2598 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2600 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2601 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2602 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2607 MI.eraseFromParent();
2612LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2614 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2615 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2616 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2617 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2618 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2631 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2638 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2642 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2643 {ShiftL, ShiftR},
MI.getFlags());
2648 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2651 MI.eraseFromParent();
2656LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2665 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2667 LLT SrcTy = MRI.getType(
LHS);
2668 LLT OverflowTy = MRI.getType(OriginalOverflow);
2675 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2676 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2677 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2684 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2686 MachineInstrBuilder Mulo;
2687 if (WideMulCanOverflow)
2688 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2689 {LeftOperand, RightOperand});
2691 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2696 MachineInstrBuilder ExtResult;
2703 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2707 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2710 if (WideMulCanOverflow) {
2718 MI.eraseFromParent();
2724 unsigned Opcode =
MI.getOpcode();
2728 case TargetOpcode::G_ATOMICRMW_XCHG:
2729 case TargetOpcode::G_ATOMICRMW_ADD:
2730 case TargetOpcode::G_ATOMICRMW_SUB:
2731 case TargetOpcode::G_ATOMICRMW_AND:
2732 case TargetOpcode::G_ATOMICRMW_OR:
2733 case TargetOpcode::G_ATOMICRMW_XOR:
2734 case TargetOpcode::G_ATOMICRMW_MIN:
2735 case TargetOpcode::G_ATOMICRMW_MAX:
2736 case TargetOpcode::G_ATOMICRMW_UMIN:
2737 case TargetOpcode::G_ATOMICRMW_UMAX:
2738 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2744 case TargetOpcode::G_ATOMIC_CMPXCHG:
2745 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2752 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2762 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2767 case TargetOpcode::G_EXTRACT:
2768 return widenScalarExtract(
MI, TypeIdx, WideTy);
2769 case TargetOpcode::G_INSERT:
2770 return widenScalarInsert(
MI, TypeIdx, WideTy);
2771 case TargetOpcode::G_MERGE_VALUES:
2772 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2773 case TargetOpcode::G_UNMERGE_VALUES:
2774 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2775 case TargetOpcode::G_SADDO:
2776 case TargetOpcode::G_SSUBO:
2777 case TargetOpcode::G_UADDO:
2778 case TargetOpcode::G_USUBO:
2779 case TargetOpcode::G_SADDE:
2780 case TargetOpcode::G_SSUBE:
2781 case TargetOpcode::G_UADDE:
2782 case TargetOpcode::G_USUBE:
2783 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2784 case TargetOpcode::G_UMULO:
2785 case TargetOpcode::G_SMULO:
2786 return widenScalarMulo(
MI, TypeIdx, WideTy);
2787 case TargetOpcode::G_SADDSAT:
2788 case TargetOpcode::G_SSUBSAT:
2789 case TargetOpcode::G_SSHLSAT:
2790 case TargetOpcode::G_UADDSAT:
2791 case TargetOpcode::G_USUBSAT:
2792 case TargetOpcode::G_USHLSAT:
2793 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2794 case TargetOpcode::G_CTTZ:
2795 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2796 case TargetOpcode::G_CTLZ:
2797 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
2798 case TargetOpcode::G_CTLS:
2799 case TargetOpcode::G_CTPOP: {
2812 case TargetOpcode::G_CTTZ:
2813 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2814 ExtOpc = TargetOpcode::G_ANYEXT;
2816 case TargetOpcode::G_CTLS:
2817 ExtOpc = TargetOpcode::G_SEXT;
2820 ExtOpc = TargetOpcode::G_ZEXT;
2823 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2824 LLT CurTy = MRI.getType(SrcReg);
2825 unsigned NewOpc = Opcode;
2826 if (NewOpc == TargetOpcode::G_CTTZ) {
2833 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2835 NewOpc = TargetOpcode::G_CTTZ_ZERO_UNDEF;
2840 if (Opcode == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
2850 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2852 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2855 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff));
2858 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2859 MI.eraseFromParent();
2862 case TargetOpcode::G_BSWAP: {
2866 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2867 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2868 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2871 MI.getOperand(0).setReg(DstExt);
2875 LLT Ty = MRI.getType(DstReg);
2877 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2878 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2884 case TargetOpcode::G_BITREVERSE: {
2888 LLT Ty = MRI.getType(DstReg);
2891 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2893 MI.getOperand(0).setReg(DstExt);
2896 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2897 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2902 case TargetOpcode::G_FREEZE:
2903 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2910 case TargetOpcode::G_ABS:
2917 case TargetOpcode::G_ADD:
2918 case TargetOpcode::G_AND:
2919 case TargetOpcode::G_MUL:
2920 case TargetOpcode::G_OR:
2921 case TargetOpcode::G_XOR:
2922 case TargetOpcode::G_SUB:
2923 case TargetOpcode::G_SHUFFLE_VECTOR:
2934 case TargetOpcode::G_SBFX:
2935 case TargetOpcode::G_UBFX:
2949 case TargetOpcode::G_SHL:
2965 case TargetOpcode::G_ROTR:
2966 case TargetOpcode::G_ROTL:
2975 case TargetOpcode::G_SDIV:
2976 case TargetOpcode::G_SREM:
2977 case TargetOpcode::G_SMIN:
2978 case TargetOpcode::G_SMAX:
2979 case TargetOpcode::G_ABDS:
2987 case TargetOpcode::G_SDIVREM:
2997 case TargetOpcode::G_ASHR:
2998 case TargetOpcode::G_LSHR:
3002 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3003 : TargetOpcode::G_ZEXT;
3016 case TargetOpcode::G_UDIV:
3017 case TargetOpcode::G_UREM:
3018 case TargetOpcode::G_ABDU:
3025 case TargetOpcode::G_UDIVREM:
3034 case TargetOpcode::G_UMIN:
3035 case TargetOpcode::G_UMAX: {
3036 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3038 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3042 ? TargetOpcode::G_SEXT
3043 : TargetOpcode::G_ZEXT;
3053 case TargetOpcode::G_SELECT:
3063 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3070 case TargetOpcode::G_FPEXT:
3078 case TargetOpcode::G_FPTOSI:
3079 case TargetOpcode::G_FPTOUI:
3080 case TargetOpcode::G_INTRINSIC_LRINT:
3081 case TargetOpcode::G_INTRINSIC_LLRINT:
3082 case TargetOpcode::G_IS_FPCLASS:
3092 case TargetOpcode::G_SITOFP:
3102 case TargetOpcode::G_UITOFP:
3112 case TargetOpcode::G_FPTOSI_SAT:
3113 case TargetOpcode::G_FPTOUI_SAT:
3118 LLT Ty = MRI.getType(OldDst);
3119 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3121 MI.getOperand(0).setReg(ExtReg);
3122 uint64_t ShortBits = Ty.getScalarSizeInBits();
3125 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3136 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3137 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3145 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3153 case TargetOpcode::G_LOAD:
3154 case TargetOpcode::G_SEXTLOAD:
3155 case TargetOpcode::G_ZEXTLOAD:
3161 case TargetOpcode::G_STORE: {
3165 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3166 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3167 if (!Ty.isScalar()) {
3175 MI.setMemRefs(MF, {NewMMO});
3182 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3183 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3189 case TargetOpcode::G_CONSTANT: {
3192 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3193 MRI.getType(
MI.getOperand(0).getReg()));
3194 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3195 ExtOpc == TargetOpcode::G_ANYEXT) &&
3198 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3202 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3208 case TargetOpcode::G_FCONSTANT: {
3214 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3216 MI.eraseFromParent();
3219 case TargetOpcode::G_IMPLICIT_DEF: {
3225 case TargetOpcode::G_BRCOND:
3231 case TargetOpcode::G_FCMP:
3242 case TargetOpcode::G_ICMP:
3247 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3251 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3252 unsigned ExtOpcode =
3256 ? TargetOpcode::G_SEXT
3257 : TargetOpcode::G_ZEXT;
3264 case TargetOpcode::G_PTR_ADD:
3265 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3271 case TargetOpcode::G_PHI: {
3272 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3275 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3287 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3290 LLT VecTy = MRI.getType(VecReg);
3296 TargetOpcode::G_ANYEXT);
3310 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3326 LLT VecTy = MRI.getType(VecReg);
3345 case TargetOpcode::G_FADD:
3346 case TargetOpcode::G_FMUL:
3347 case TargetOpcode::G_FSUB:
3348 case TargetOpcode::G_FMA:
3349 case TargetOpcode::G_FMAD:
3350 case TargetOpcode::G_FNEG:
3351 case TargetOpcode::G_FABS:
3352 case TargetOpcode::G_FCANONICALIZE:
3353 case TargetOpcode::G_FMINNUM:
3354 case TargetOpcode::G_FMAXNUM:
3355 case TargetOpcode::G_FMINNUM_IEEE:
3356 case TargetOpcode::G_FMAXNUM_IEEE:
3357 case TargetOpcode::G_FMINIMUM:
3358 case TargetOpcode::G_FMAXIMUM:
3359 case TargetOpcode::G_FMINIMUMNUM:
3360 case TargetOpcode::G_FMAXIMUMNUM:
3361 case TargetOpcode::G_FDIV:
3362 case TargetOpcode::G_FREM:
3363 case TargetOpcode::G_FCEIL:
3364 case TargetOpcode::G_FFLOOR:
3365 case TargetOpcode::G_FCOS:
3366 case TargetOpcode::G_FSIN:
3367 case TargetOpcode::G_FTAN:
3368 case TargetOpcode::G_FACOS:
3369 case TargetOpcode::G_FASIN:
3370 case TargetOpcode::G_FATAN:
3371 case TargetOpcode::G_FATAN2:
3372 case TargetOpcode::G_FCOSH:
3373 case TargetOpcode::G_FSINH:
3374 case TargetOpcode::G_FTANH:
3375 case TargetOpcode::G_FLOG10:
3376 case TargetOpcode::G_FLOG:
3377 case TargetOpcode::G_FLOG2:
3378 case TargetOpcode::G_FRINT:
3379 case TargetOpcode::G_FNEARBYINT:
3380 case TargetOpcode::G_FSQRT:
3381 case TargetOpcode::G_FEXP:
3382 case TargetOpcode::G_FEXP2:
3383 case TargetOpcode::G_FEXP10:
3384 case TargetOpcode::G_FPOW:
3385 case TargetOpcode::G_INTRINSIC_TRUNC:
3386 case TargetOpcode::G_INTRINSIC_ROUND:
3387 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3391 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3397 case TargetOpcode::G_FMODF: {
3407 case TargetOpcode::G_FPOWI:
3408 case TargetOpcode::G_FLDEXP:
3409 case TargetOpcode::G_STRICT_FLDEXP: {
3411 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3432 case TargetOpcode::G_FFREXP: {
3445 case TargetOpcode::G_LROUND:
3446 case TargetOpcode::G_LLROUND:
3457 case TargetOpcode::G_INTTOPTR:
3465 case TargetOpcode::G_PTRTOINT:
3473 case TargetOpcode::G_BUILD_VECTOR: {
3477 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3483 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3491 case TargetOpcode::G_SEXT_INREG:
3500 case TargetOpcode::G_PTRMASK: {
3508 case TargetOpcode::G_VECREDUCE_ADD: {
3517 case TargetOpcode::G_VECREDUCE_FADD:
3518 case TargetOpcode::G_VECREDUCE_FMUL:
3519 case TargetOpcode::G_VECREDUCE_FMIN:
3520 case TargetOpcode::G_VECREDUCE_FMAX:
3521 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3522 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3527 LLT VecTy = MRI.getType(VecReg);
3534 case TargetOpcode::G_VSCALE: {
3541 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3546 case TargetOpcode::G_SPLAT_VECTOR: {
3555 case TargetOpcode::G_INSERT_SUBVECTOR: {
3563 LLT SubVecTy = MRI.getType(SubVec);
3567 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3568 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3569 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3573 auto SplatZero =
MIRBuilder.buildSplatVector(
3578 MI.eraseFromParent();
3587 auto Unmerge =
B.buildUnmerge(Ty, Src);
3588 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3597 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3599 LLT DstLLT =
MRI.getType(DstReg);
3611 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3620 MI.eraseFromParent();
3631 MI.eraseFromParent();
3638 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3639 if (SrcTy.isVector()) {
3643 if (DstTy.isVector()) {
3644 int NumDstElt = DstTy.getNumElements();
3645 int NumSrcElt = SrcTy.getNumElements();
3648 LLT DstCastTy = DstEltTy;
3649 LLT SrcPartTy = SrcEltTy;
3653 if (NumSrcElt < NumDstElt) {
3664 SrcPartTy = SrcEltTy;
3665 }
else if (NumSrcElt > NumDstElt) {
3677 DstCastTy = DstEltTy;
3682 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3686 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3687 MI.eraseFromParent();
3691 if (DstTy.isVector()) {
3694 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3695 MI.eraseFromParent();
3711 unsigned NewEltSize,
3712 unsigned OldEltSize) {
3713 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3714 LLT IdxTy =
B.getMRI()->getType(Idx);
3717 auto OffsetMask =
B.buildConstant(
3719 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3720 return B.buildShl(IdxTy, OffsetIdx,
3721 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3736 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3740 unsigned OldNumElts = SrcVecTy.getNumElements();
3747 if (NewNumElts > OldNumElts) {
3758 if (NewNumElts % OldNumElts != 0)
3762 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3766 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3769 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3771 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3772 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3773 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3774 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3775 NewOps[
I] = Elt.getReg(0);
3778 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3780 MI.eraseFromParent();
3784 if (NewNumElts < OldNumElts) {
3785 if (NewEltSize % OldEltSize != 0)
3807 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3808 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3811 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3815 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3816 ScaledIdx).getReg(0);
3824 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3826 MI.eraseFromParent();
3840 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3841 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3842 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3843 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3846 auto EltMask =
B.buildConstant(
3850 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3851 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3854 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3858 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3872 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3873 MI.getFirst4RegLLTs();
3885 if (NewNumElts < OldNumElts) {
3886 if (NewEltSize % OldEltSize != 0)
3895 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3896 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3899 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3903 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3904 ScaledIdx).getReg(0);
3914 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3915 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3919 MI.eraseFromParent();
3949 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3953 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3954 return UnableToLegalize;
3959 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3961 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3970 MI.eraseFromParent();
3988 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3989 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3999 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4000 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4002 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4003 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4005 MI.eraseFromParent();
4035 LLT DstTy = MRI.getType(Dst);
4036 LLT SrcTy = MRI.getType(Src);
4042 if (DstTy == CastTy)
4050 if (CastEltSize < DstEltSize)
4053 auto AdjustAmt = CastEltSize / DstEltSize;
4054 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4055 SrcTyMinElts % AdjustAmt != 0)
4060 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4061 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4064 ES->eraseFromParent();
4099 LLT DstTy = MRI.getType(Dst);
4100 LLT BigVecTy = MRI.getType(BigVec);
4101 LLT SubVecTy = MRI.getType(SubVec);
4103 if (DstTy == CastTy)
4118 if (CastEltSize < DstEltSize)
4121 auto AdjustAmt = CastEltSize / DstEltSize;
4122 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4123 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4129 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4130 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4132 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4135 ES->eraseFromParent();
4143 LLT DstTy = MRI.getType(DstReg);
4151 if (MemSizeInBits != MemStoreSizeInBits) {
4168 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4172 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4173 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4175 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4178 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4180 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4183 if (DstTy != LoadTy)
4191 if (
MIRBuilder.getDataLayout().isBigEndian())
4209 uint64_t LargeSplitSize, SmallSplitSize;
4214 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4221 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4224 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4235 if (Alignment.
value() * 8 > MemSizeInBits &&
4240 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4257 LLT PtrTy = MRI.getType(PtrReg);
4260 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4264 LargeSplitSize / 8);
4265 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4266 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4268 SmallPtr, *SmallMMO);
4270 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4271 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4273 if (AnyExtTy == DstTy)
4274 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4276 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4280 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4300 LLT SrcTy = MRI.getType(SrcReg);
4308 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4314 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4316 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4320 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4324 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4339 uint64_t LargeSplitSize, SmallSplitSize;
4346 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4349 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4358 if (SrcTy.isPointer()) {
4360 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4363 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4366 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4367 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4370 LLT PtrTy = MRI.getType(PtrReg);
4373 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4379 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4380 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4389 LLT SrcTy = MRI.getType(SrcReg);
4395 assert(SrcTy.isVector() &&
"Expect a vector store type");
4402 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4406 auto Elt =
MIRBuilder.buildExtractVectorElement(
4407 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4408 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4409 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4415 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4416 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4420 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4431 switch (
MI.getOpcode()) {
4432 case TargetOpcode::G_LOAD: {
4450 case TargetOpcode::G_STORE: {
4466 case TargetOpcode::G_SELECT: {
4470 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4472 dbgs() <<
"bitcast action not implemented for vector select\n");
4483 case TargetOpcode::G_AND:
4484 case TargetOpcode::G_OR:
4485 case TargetOpcode::G_XOR: {
4493 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4495 case TargetOpcode::G_INSERT_VECTOR_ELT:
4497 case TargetOpcode::G_CONCAT_VECTORS:
4499 case TargetOpcode::G_SHUFFLE_VECTOR:
4501 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4503 case TargetOpcode::G_INSERT_SUBVECTOR:
4511void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4521 switch(
MI.getOpcode()) {
4524 case TargetOpcode::G_FCONSTANT:
4526 case TargetOpcode::G_BITCAST:
4528 case TargetOpcode::G_SREM:
4529 case TargetOpcode::G_UREM: {
4530 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4532 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4533 {MI.getOperand(1), MI.getOperand(2)});
4535 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4537 MI.eraseFromParent();
4540 case TargetOpcode::G_SADDO:
4541 case TargetOpcode::G_SSUBO:
4543 case TargetOpcode::G_SADDE:
4545 case TargetOpcode::G_SSUBE:
4547 case TargetOpcode::G_UMULH:
4548 case TargetOpcode::G_SMULH:
4550 case TargetOpcode::G_SMULO:
4551 case TargetOpcode::G_UMULO: {
4554 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4555 LLT Ty = MRI.getType(Res);
4557 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4558 ? TargetOpcode::G_SMULH
4559 : TargetOpcode::G_UMULH;
4563 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4564 MI.removeOperand(1);
4567 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4575 if (Opcode == TargetOpcode::G_SMULH) {
4576 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4577 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4584 case TargetOpcode::G_FNEG: {
4585 auto [Res, SubByReg] =
MI.getFirst2Regs();
4586 LLT Ty = MRI.getType(Res);
4590 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4591 MI.eraseFromParent();
4594 case TargetOpcode::G_FSUB:
4595 case TargetOpcode::G_STRICT_FSUB: {
4596 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4597 LLT Ty = MRI.getType(Res);
4602 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4603 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4607 MI.eraseFromParent();
4610 case TargetOpcode::G_FMAD:
4612 case TargetOpcode::G_FFLOOR:
4614 case TargetOpcode::G_LROUND:
4615 case TargetOpcode::G_LLROUND: {
4618 LLT SrcTy = MRI.getType(SrcReg);
4619 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4622 MI.eraseFromParent();
4625 case TargetOpcode::G_INTRINSIC_ROUND:
4627 case TargetOpcode::G_FRINT: {
4630 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4633 case TargetOpcode::G_INTRINSIC_LRINT:
4634 case TargetOpcode::G_INTRINSIC_LLRINT: {
4637 LLT SrcTy = MRI.getType(SrcReg);
4639 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4641 MI.eraseFromParent();
4644 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4645 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4646 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4647 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4648 **
MI.memoperands_begin());
4650 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4651 MI.eraseFromParent();
4654 case TargetOpcode::G_LOAD:
4655 case TargetOpcode::G_SEXTLOAD:
4656 case TargetOpcode::G_ZEXTLOAD:
4658 case TargetOpcode::G_STORE:
4660 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4661 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4662 case TargetOpcode::G_CTLZ:
4663 case TargetOpcode::G_CTTZ:
4664 case TargetOpcode::G_CTPOP:
4665 case TargetOpcode::G_CTLS:
4668 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4670 Register NewRes = MRI.cloneVirtualRegister(Res);
4677 MI.eraseFromParent();
4681 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4682 const LLT CondTy = MRI.getType(CarryOut);
4683 const LLT Ty = MRI.getType(Res);
4685 Register NewRes = MRI.cloneVirtualRegister(Res);
4688 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4694 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4695 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4702 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4707 MI.eraseFromParent();
4711 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4716 MI.eraseFromParent();
4720 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4721 const LLT CondTy = MRI.getType(BorrowOut);
4722 const LLT Ty = MRI.getType(Res);
4725 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4731 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4732 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4739 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4740 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4742 MI.eraseFromParent();
4778 case G_MERGE_VALUES:
4780 case G_UNMERGE_VALUES:
4782 case TargetOpcode::G_SEXT_INREG: {
4783 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4784 int64_t SizeInBits =
MI.getOperand(2).getImm();
4786 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4787 LLT DstTy = MRI.getType(DstReg);
4788 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4791 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4792 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4793 MI.eraseFromParent();
4796 case G_EXTRACT_VECTOR_ELT:
4797 case G_INSERT_VECTOR_ELT:
4799 case G_SHUFFLE_VECTOR:
4801 case G_VECTOR_COMPRESS:
4803 case G_DYN_STACKALLOC:
4807 case G_STACKRESTORE:
4817 case G_READ_REGISTER:
4818 case G_WRITE_REGISTER:
4825 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4826 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4832 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4837 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4848 bool IsSigned =
MI.getOpcode() == G_ABDS;
4849 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4850 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4851 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4875 case G_MEMCPY_INLINE:
4876 return lowerMemcpyInline(
MI);
4887 case G_ATOMICRMW_SUB: {
4888 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4889 const LLT ValTy = MRI.getType(Val);
4893 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4894 MI.eraseFromParent();
4917 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4921 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4927 Align StackTypeAlign =
4934 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4935 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4940 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4952 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4955 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4966 "Converting bits to bytes lost precision");
4972 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4973 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4975 if (IdxTy != MRI.getType(Index))
4976 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4981 LLT PtrTy = MRI.getType(VecPtr);
4982 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4990 std::initializer_list<unsigned> NonVecOpIndices) {
4991 if (
MI.getNumMemOperands() != 0)
4994 LLT VecTy =
MRI.getType(
MI.getReg(0));
5008 if (!Ty.isVector()) {
5014 if (Ty.getNumElements() != NumElts)
5029 assert(Ty.isVector() &&
"Expected vector type");
5031 int NumParts, NumLeftover;
5032 std::tie(NumParts, NumLeftover) =
5035 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5036 for (
int i = 0; i < NumParts; ++i) {
5041 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5050 for (
unsigned i = 0; i <
N; ++i) {
5052 Ops.push_back(
Op.getReg());
5053 else if (
Op.isImm())
5054 Ops.push_back(
Op.getImm());
5055 else if (
Op.isPredicate())
5077 std::initializer_list<unsigned> NonVecOpIndices) {
5079 "Non-compatible opcode or not specified non-vector operands");
5080 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5082 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5083 unsigned NumDefs =
MI.getNumDefs();
5091 for (
unsigned i = 0; i < NumDefs; ++i) {
5092 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5100 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5101 ++UseIdx, ++UseNo) {
5104 MI.getOperand(UseIdx));
5113 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5117 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5119 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5120 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5123 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5124 Uses.push_back(InputOpsPieces[InputNo][i]);
5127 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5128 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5133 for (
unsigned i = 0; i < NumDefs; ++i)
5134 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5136 for (
unsigned i = 0; i < NumDefs; ++i)
5137 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5140 MI.eraseFromParent();
5147 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5149 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5150 unsigned NumDefs =
MI.getNumDefs();
5154 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5159 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5160 UseIdx += 2, ++UseNo) {
5168 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5170 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5171 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5173 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5176 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5177 Phi.addUse(InputOpsPieces[j][i]);
5178 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5188 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5190 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5193 MI.eraseFromParent();
5201 const int NumDst =
MI.getNumOperands() - 1;
5202 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5203 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5204 LLT SrcTy = MRI.getType(SrcReg);
5206 if (TypeIdx != 1 || NarrowTy == DstTy)
5213 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5216 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5230 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5231 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5232 const int PartsPerUnmerge = NumDst / NumUnmerge;
5234 for (
int I = 0;
I != NumUnmerge; ++
I) {
5235 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5237 for (
int J = 0; J != PartsPerUnmerge; ++J)
5238 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5239 MIB.addUse(Unmerge.getReg(
I));
5242 MI.eraseFromParent();
5249 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5253 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5255 if (NarrowTy == SrcTy)
5263 assert(SrcTy.isVector() &&
"Expected vector types");
5265 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5279 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5280 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5281 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5287 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5288 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5289 ++i,
Offset += NumNarrowTyElts) {
5292 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5295 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5296 MI.eraseFromParent();
5300 assert(TypeIdx == 0 &&
"Bad type index");
5301 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5316 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5317 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5319 for (
unsigned i = 0; i < NumParts; ++i) {
5321 for (
unsigned j = 0; j < NumElts; ++j)
5322 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5324 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5327 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5328 MI.eraseFromParent();
5336 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5338 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5340 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5342 InsertVal =
MI.getOperand(2).getReg();
5344 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5345 LLT VecTy = MRI.getType(SrcVec);
5351 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5355 MI.eraseFromParent();
5364 SplitPieces[IdxVal] = InsertVal;
5365 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5367 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5371 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5374 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5375 TargetOpcode::G_ANYEXT);
5379 LLT IdxTy = MRI.getType(Idx);
5380 int64_t PartIdx = IdxVal / NewNumElts;
5382 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5385 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5388 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5389 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5390 VecParts[PartIdx] = InsertPart.getReg(0);
5394 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5396 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5400 MI.eraseFromParent();
5420 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5432 LLT ValTy = MRI.getType(ValReg);
5441 int NumLeftover = -1;
5447 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5449 NumParts = NarrowRegs.
size();
5450 NumLeftover = NarrowLeftoverRegs.
size();
5457 LLT PtrTy = MRI.getType(AddrReg);
5460 unsigned TotalSize = ValTy.getSizeInBits();
5467 auto MMO = LdStMI.
getMMO();
5469 unsigned NumParts,
unsigned Offset) ->
unsigned {
5472 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5474 unsigned ByteOffset =
Offset / 8;
5477 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5484 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5485 ValRegs.push_back(Dst);
5486 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5488 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5497 unsigned HandledOffset =
5498 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5502 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5505 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5506 LeftoverTy, NarrowLeftoverRegs);
5520 switch (
MI.getOpcode()) {
5521 case G_IMPLICIT_DEF:
5537 case G_FCANONICALIZE:
5554 case G_INTRINSIC_LRINT:
5555 case G_INTRINSIC_LLRINT:
5556 case G_INTRINSIC_ROUND:
5557 case G_INTRINSIC_ROUNDEVEN:
5560 case G_INTRINSIC_TRUNC:
5588 case G_FMINNUM_IEEE:
5589 case G_FMAXNUM_IEEE:
5611 case G_CTLZ_ZERO_UNDEF:
5613 case G_CTTZ_ZERO_UNDEF:
5629 case G_ADDRSPACE_CAST:
5642 case G_STRICT_FLDEXP:
5651 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5656 case G_UNMERGE_VALUES:
5658 case G_BUILD_VECTOR:
5659 assert(TypeIdx == 0 &&
"not a vector type index");
5661 case G_CONCAT_VECTORS:
5665 case G_EXTRACT_VECTOR_ELT:
5666 case G_INSERT_VECTOR_ELT:
5675 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5676 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5678 case G_SHUFFLE_VECTOR:
5684 case G_INTRINSIC_FPTRUNC_ROUND:
5694 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5695 "Not a bitcast operation");
5700 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5702 unsigned NewElemCount =
5705 if (NewElemCount == 1) {
5708 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5715 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5724 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5725 MI.eraseFromParent();
5731 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5735 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5736 MI.getFirst3RegLLTs();
5739 if (DstTy != Src1Ty)
5741 if (DstTy != Src2Ty)
5756 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5772 unsigned InputUsed[2] = {-1U, -1U};
5773 unsigned FirstMaskIdx =
High * NewElts;
5774 bool UseBuildVector =
false;
5775 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5777 int Idx = Mask[FirstMaskIdx + MaskOffset];
5782 if (
Input >= std::size(Inputs)) {
5789 Idx -=
Input * NewElts;
5793 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5794 if (InputUsed[OpNo] ==
Input) {
5797 }
else if (InputUsed[OpNo] == -1U) {
5799 InputUsed[OpNo] =
Input;
5804 if (OpNo >= std::size(InputUsed)) {
5807 UseBuildVector =
true;
5812 Ops.push_back(Idx + OpNo * NewElts);
5815 if (UseBuildVector) {
5820 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5822 int Idx = Mask[FirstMaskIdx + MaskOffset];
5827 if (
Input >= std::size(Inputs)) {
5834 Idx -=
Input * NewElts;
5838 .buildExtractVectorElement(
5839 EltTy, Inputs[
Input],
5845 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5846 }
else if (InputUsed[0] == -1U) {
5848 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5849 }
else if (NewElts == 1) {
5850 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
5852 Register Op0 = Inputs[InputUsed[0]];
5856 : Inputs[InputUsed[1]];
5858 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5865 MI.eraseFromParent();
5878 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5884 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5887 const unsigned NumParts =
5889 : SrcTy.getNumElements();
5893 if (DstTy != NarrowTy)
5899 unsigned NumPartsLeft = NumParts;
5900 while (NumPartsLeft > 1) {
5901 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5904 .buildInstr(ScalarOpc, {NarrowTy},
5905 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5908 SplitSrcs = PartialResults;
5909 PartialResults.
clear();
5910 NumPartsLeft = SplitSrcs.
size();
5914 MI.eraseFromParent();
5919 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5920 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5923 MI.eraseFromParent();
5927 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5929 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5937 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5940 Register Acc = PartialReductions[0];
5941 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5942 if (Part == NumParts - 1) {
5944 {Acc, PartialReductions[Part]});
5947 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5951 MI.eraseFromParent();
5957 unsigned int TypeIdx,
5959 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5960 MI.getFirst3RegLLTs();
5961 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5965 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5966 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5967 "Unexpected vecreduce opcode");
5968 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5969 ? TargetOpcode::G_FADD
5970 : TargetOpcode::G_FMUL;
5973 unsigned NumParts = SrcTy.getNumElements();
5976 for (
unsigned i = 0; i < NumParts; i++)
5977 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5981 MI.eraseFromParent();
5988 unsigned ScalarOpc) {
5996 while (SplitSrcs.
size() > 1) {
5998 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6006 SplitSrcs = std::move(PartialRdxs);
6010 MI.getOperand(1).setReg(SplitSrcs[0]);
6017 const LLT HalfTy,
const LLT AmtTy) {
6019 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6020 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6024 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6025 MI.eraseFromParent();
6031 unsigned VTBits = 2 * NVTBits;
6034 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6035 if (Amt.
ugt(VTBits)) {
6037 }
else if (Amt.
ugt(NVTBits)) {
6040 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6041 }
else if (Amt == NVTBits) {
6049 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6052 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6053 if (Amt.
ugt(VTBits)) {
6055 }
else if (Amt.
ugt(NVTBits)) {
6057 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6059 }
else if (Amt == NVTBits) {
6063 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6065 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6067 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6073 if (Amt.
ugt(VTBits)) {
6075 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6076 }
else if (Amt.
ugt(NVTBits)) {
6078 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6080 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6081 }
else if (Amt == NVTBits) {
6084 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6086 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6088 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6090 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6097 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6098 MI.eraseFromParent();
6114 LLT DstTy = MRI.getType(DstReg);
6119 LLT ShiftAmtTy = MRI.getType(Amt);
6121 if (DstEltSize % 2 != 0)
6137 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6148 const unsigned NewBitSize = DstEltSize / 2;
6160 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6162 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6163 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6166 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6167 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6169 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6174 switch (
MI.getOpcode()) {
6175 case TargetOpcode::G_SHL: {
6177 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6179 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6180 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6181 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6184 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6185 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6187 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6189 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6191 ResultRegs[0] =
Lo.getReg(0);
6192 ResultRegs[1] =
Hi.getReg(0);
6195 case TargetOpcode::G_LSHR:
6196 case TargetOpcode::G_ASHR: {
6198 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6200 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6201 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6202 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6206 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6209 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6210 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6212 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6216 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6218 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6220 ResultRegs[0] =
Lo.getReg(0);
6221 ResultRegs[1] =
Hi.getReg(0);
6228 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6229 MI.eraseFromParent();
6238 LLT TargetTy,
LLT ShiftAmtTy) {
6241 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6243 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6244 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6245 const bool NeedsInterWordShift = ShiftBits != 0;
6248 case TargetOpcode::G_SHL: {
6251 if (PartIdx < ShiftWords)
6254 unsigned SrcIdx = PartIdx - ShiftWords;
6255 if (!NeedsInterWordShift)
6256 return SrcParts[SrcIdx];
6261 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6265 return Hi.getReg(0);
6268 case TargetOpcode::G_LSHR: {
6269 unsigned SrcIdx = PartIdx + ShiftWords;
6270 if (SrcIdx >= NumParts)
6272 if (!NeedsInterWordShift)
6273 return SrcParts[SrcIdx];
6277 if (SrcIdx + 1 < NumParts) {
6278 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6282 return Lo.getReg(0);
6285 case TargetOpcode::G_ASHR: {
6287 unsigned SrcIdx = PartIdx + ShiftWords;
6288 if (SrcIdx >= NumParts)
6290 if (!NeedsInterWordShift)
6291 return SrcParts[SrcIdx];
6296 (SrcIdx == NumParts - 1)
6300 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6322 unsigned MainOpcode =
6323 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6327 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6336 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6337 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6339 auto IsZeroBitShift =
6347 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6348 : TargetOpcode::G_SHL;
6351 auto TargetBitsConst =
6353 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6358 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6363 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6365 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6369 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6382 LLT DstTy = MRI.getType(DstReg);
6386 const unsigned NumParts = DstBits / TargetBits;
6388 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6398 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6399 MI.eraseFromParent();
6404 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6405 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6411 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6415 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6418 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6419 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6423 for (
unsigned I = 0;
I < NumParts; ++
I)
6425 Params, TargetTy, ShiftAmtTy);
6427 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6428 MI.eraseFromParent();
6437 LLT DstTy = MRI.getType(DstReg);
6438 LLT ShiftAmtTy = MRI.getType(AmtReg);
6442 const unsigned NumParts = DstBits / TargetBits;
6444 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6461 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6473 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6474 auto TargetBitsLog2Const =
6475 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6476 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6479 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6481 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6489 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6490 auto TargetBitsMinusOneConst =
6491 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6493 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6494 TargetBitsMinusOneConst)
6497 FillValue = ZeroReg;
6505 for (
unsigned I = 0;
I < NumParts; ++
I) {
6507 Register InBoundsResult = FillValue;
6517 for (
unsigned K = 0; K < NumParts; ++K) {
6518 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6520 WordShift, WordShiftKConst);
6532 switch (
MI.getOpcode()) {
6533 case TargetOpcode::G_SHL:
6534 MainSrcIdx = (int)
I - (
int)K;
6535 CarrySrcIdx = MainSrcIdx - 1;
6537 case TargetOpcode::G_LSHR:
6538 case TargetOpcode::G_ASHR:
6539 MainSrcIdx = (int)
I + (
int)K;
6540 CarrySrcIdx = MainSrcIdx + 1;
6548 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6549 Register MainOp = SrcParts[MainSrcIdx];
6553 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6554 CarryOp = SrcParts[CarrySrcIdx];
6555 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6556 CarrySrcIdx >= (
int)NumParts)
6557 CarryOp = FillValue;
6563 ResultForK = FillValue;
6569 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6576 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6580 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6581 MI.eraseFromParent();
6588 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6591 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6606 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6611 "getNeutralElementForVecReduce called with invalid opcode!");
6612 case TargetOpcode::G_VECREDUCE_ADD:
6613 case TargetOpcode::G_VECREDUCE_OR:
6614 case TargetOpcode::G_VECREDUCE_XOR:
6615 case TargetOpcode::G_VECREDUCE_UMAX:
6617 case TargetOpcode::G_VECREDUCE_MUL:
6619 case TargetOpcode::G_VECREDUCE_AND:
6620 case TargetOpcode::G_VECREDUCE_UMIN:
6623 case TargetOpcode::G_VECREDUCE_SMAX:
6626 case TargetOpcode::G_VECREDUCE_SMIN:
6629 case TargetOpcode::G_VECREDUCE_FADD:
6631 case TargetOpcode::G_VECREDUCE_FMUL:
6633 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6634 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6635 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6636 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6644 unsigned Opc =
MI.getOpcode();
6646 case TargetOpcode::G_IMPLICIT_DEF:
6647 case TargetOpcode::G_LOAD: {
6655 case TargetOpcode::G_STORE:
6662 case TargetOpcode::G_AND:
6663 case TargetOpcode::G_OR:
6664 case TargetOpcode::G_XOR:
6665 case TargetOpcode::G_ADD:
6666 case TargetOpcode::G_SUB:
6667 case TargetOpcode::G_MUL:
6668 case TargetOpcode::G_FADD:
6669 case TargetOpcode::G_FSUB:
6670 case TargetOpcode::G_FMUL:
6671 case TargetOpcode::G_FDIV:
6672 case TargetOpcode::G_FCOPYSIGN:
6673 case TargetOpcode::G_UADDSAT:
6674 case TargetOpcode::G_USUBSAT:
6675 case TargetOpcode::G_SADDSAT:
6676 case TargetOpcode::G_SSUBSAT:
6677 case TargetOpcode::G_SMIN:
6678 case TargetOpcode::G_SMAX:
6679 case TargetOpcode::G_UMIN:
6680 case TargetOpcode::G_UMAX:
6681 case TargetOpcode::G_FMINNUM:
6682 case TargetOpcode::G_FMAXNUM:
6683 case TargetOpcode::G_FMINNUM_IEEE:
6684 case TargetOpcode::G_FMAXNUM_IEEE:
6685 case TargetOpcode::G_FMINIMUM:
6686 case TargetOpcode::G_FMAXIMUM:
6687 case TargetOpcode::G_FMINIMUMNUM:
6688 case TargetOpcode::G_FMAXIMUMNUM:
6689 case TargetOpcode::G_STRICT_FADD:
6690 case TargetOpcode::G_STRICT_FSUB:
6691 case TargetOpcode::G_STRICT_FMUL: {
6699 case TargetOpcode::G_SHL:
6700 case TargetOpcode::G_ASHR:
6701 case TargetOpcode::G_LSHR: {
6707 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6713 case TargetOpcode::G_FMA:
6714 case TargetOpcode::G_STRICT_FMA:
6715 case TargetOpcode::G_FSHR:
6716 case TargetOpcode::G_FSHL: {
6725 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6726 case TargetOpcode::G_EXTRACT:
6733 case TargetOpcode::G_INSERT:
6734 case TargetOpcode::G_INSERT_VECTOR_ELT:
6735 case TargetOpcode::G_FREEZE:
6736 case TargetOpcode::G_FNEG:
6737 case TargetOpcode::G_FABS:
6738 case TargetOpcode::G_FSQRT:
6739 case TargetOpcode::G_FCEIL:
6740 case TargetOpcode::G_FFLOOR:
6741 case TargetOpcode::G_FNEARBYINT:
6742 case TargetOpcode::G_FRINT:
6743 case TargetOpcode::G_INTRINSIC_ROUND:
6744 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6745 case TargetOpcode::G_INTRINSIC_TRUNC:
6746 case TargetOpcode::G_BITREVERSE:
6747 case TargetOpcode::G_BSWAP:
6748 case TargetOpcode::G_FCANONICALIZE:
6749 case TargetOpcode::G_SEXT_INREG:
6750 case TargetOpcode::G_ABS:
6751 case TargetOpcode::G_CTLZ:
6752 case TargetOpcode::G_CTPOP:
6760 case TargetOpcode::G_SELECT: {
6761 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6763 if (!CondTy.isScalar() ||
6769 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6771 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6776 if (CondTy.isVector())
6786 case TargetOpcode::G_UNMERGE_VALUES:
6788 case TargetOpcode::G_PHI:
6790 case TargetOpcode::G_SHUFFLE_VECTOR:
6792 case TargetOpcode::G_BUILD_VECTOR: {
6794 for (
auto Op :
MI.uses()) {
6802 MIRBuilder.buildDeleteTrailingVectorElements(
6803 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6804 MI.eraseFromParent();
6807 case TargetOpcode::G_SEXT:
6808 case TargetOpcode::G_ZEXT:
6809 case TargetOpcode::G_ANYEXT:
6810 case TargetOpcode::G_TRUNC:
6811 case TargetOpcode::G_FPTRUNC:
6812 case TargetOpcode::G_FPEXT:
6813 case TargetOpcode::G_FPTOSI:
6814 case TargetOpcode::G_FPTOUI:
6815 case TargetOpcode::G_FPTOSI_SAT:
6816 case TargetOpcode::G_FPTOUI_SAT:
6817 case TargetOpcode::G_SITOFP:
6818 case TargetOpcode::G_UITOFP: {
6825 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6828 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6836 case TargetOpcode::G_ICMP:
6837 case TargetOpcode::G_FCMP: {
6845 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6850 case TargetOpcode::G_BITCAST: {
6854 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6855 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6871 case TargetOpcode::G_VECREDUCE_FADD:
6872 case TargetOpcode::G_VECREDUCE_FMUL:
6873 case TargetOpcode::G_VECREDUCE_ADD:
6874 case TargetOpcode::G_VECREDUCE_MUL:
6875 case TargetOpcode::G_VECREDUCE_AND:
6876 case TargetOpcode::G_VECREDUCE_OR:
6877 case TargetOpcode::G_VECREDUCE_XOR:
6878 case TargetOpcode::G_VECREDUCE_SMAX:
6879 case TargetOpcode::G_VECREDUCE_SMIN:
6880 case TargetOpcode::G_VECREDUCE_UMAX:
6881 case TargetOpcode::G_VECREDUCE_UMIN: {
6882 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6884 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6885 auto NeutralElement = getNeutralElementForVecReduce(
6891 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6892 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6893 NeutralElement, Idx);
6897 MO.
setReg(NewVec.getReg(0));
6909 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6911 unsigned MaskNumElts = Mask.size();
6912 unsigned SrcNumElts = SrcTy.getNumElements();
6915 if (MaskNumElts == SrcNumElts)
6918 if (MaskNumElts < SrcNumElts) {
6926 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6927 MI.getOperand(1).getReg(),
6928 MI.getOperand(2).getReg(), NewMask);
6929 MI.eraseFromParent();
6934 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6935 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6944 MOps1[0] =
MI.getOperand(1).getReg();
6945 MOps2[0] =
MI.getOperand(2).getReg();
6947 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6948 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6952 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6954 if (Idx >=
static_cast<int>(SrcNumElts))
6955 Idx += PaddedMaskNumElts - SrcNumElts;
6960 if (MaskNumElts != PaddedMaskNumElts) {
6962 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6965 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6967 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6972 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6975 MI.eraseFromParent();
6981 unsigned int TypeIdx,
LLT MoreTy) {
6982 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6984 unsigned NumElts = DstTy.getNumElements();
6987 if (DstTy.isVector() && Src1Ty.isVector() &&
6988 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6996 if (DstTy != Src1Ty || DstTy != Src2Ty)
7004 for (
unsigned I = 0;
I != NumElts; ++
I) {
7006 if (Idx <
static_cast<int>(NumElts))
7009 NewMask[
I] = Idx - NumElts + WidenNumElts;
7013 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7014 MI.getOperand(1).getReg(),
7015 MI.getOperand(2).getReg(), NewMask);
7016 MI.eraseFromParent();
7025 unsigned SrcParts = Src1Regs.
size();
7026 unsigned DstParts = DstRegs.
size();
7028 unsigned DstIdx = 0;
7030 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7031 DstRegs[DstIdx] = FactorSum;
7036 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7038 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7039 i <= std::min(DstIdx, SrcParts - 1); ++i) {
7041 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7045 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7046 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7048 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7058 if (DstIdx != DstParts - 1) {
7059 MachineInstrBuilder Uaddo =
7060 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
7061 FactorSum = Uaddo.
getReg(0);
7062 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7063 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7064 MachineInstrBuilder Uaddo =
7065 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
7066 FactorSum = Uaddo.
getReg(0);
7067 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7068 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7072 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7073 for (
unsigned i = 2; i < Factors.
size(); ++i)
7074 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7077 CarrySumPrevDstIdx = CarrySum;
7078 DstRegs[DstIdx] = FactorSum;
7090 LLT DstType = MRI.getType(DstReg);
7092 if (DstType.isVector())
7095 unsigned Opcode =
MI.getOpcode();
7096 unsigned OpO, OpE, OpF;
7098 case TargetOpcode::G_SADDO:
7099 case TargetOpcode::G_SADDE:
7100 case TargetOpcode::G_UADDO:
7101 case TargetOpcode::G_UADDE:
7102 case TargetOpcode::G_ADD:
7103 OpO = TargetOpcode::G_UADDO;
7104 OpE = TargetOpcode::G_UADDE;
7105 OpF = TargetOpcode::G_UADDE;
7106 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7107 OpF = TargetOpcode::G_SADDE;
7109 case TargetOpcode::G_SSUBO:
7110 case TargetOpcode::G_SSUBE:
7111 case TargetOpcode::G_USUBO:
7112 case TargetOpcode::G_USUBE:
7113 case TargetOpcode::G_SUB:
7114 OpO = TargetOpcode::G_USUBO;
7115 OpE = TargetOpcode::G_USUBE;
7116 OpF = TargetOpcode::G_USUBE;
7117 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7118 OpF = TargetOpcode::G_SSUBE;
7125 unsigned NumDefs =
MI.getNumExplicitDefs();
7126 Register Src1 =
MI.getOperand(NumDefs).getReg();
7127 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7130 CarryDst =
MI.getOperand(1).getReg();
7131 if (
MI.getNumOperands() == NumDefs + 3)
7132 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7134 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7135 LLT LeftoverTy, DummyTy;
7137 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7142 int NarrowParts = Src1Regs.
size();
7143 Src1Regs.
append(Src1Left);
7144 Src2Regs.
append(Src2Left);
7147 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7149 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7152 if (i == e - 1 && CarryDst)
7153 CarryOut = CarryDst;
7155 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7158 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7159 {Src1Regs[i], Src2Regs[i]});
7160 }
else if (i == e - 1) {
7161 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7162 {Src1Regs[i], Src2Regs[i], CarryIn});
7164 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7165 {Src1Regs[i], Src2Regs[i], CarryIn});
7171 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7172 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7173 ArrayRef(DstRegs).drop_front(NarrowParts));
7175 MI.eraseFromParent();
7181 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7183 LLT Ty = MRI.getType(DstReg);
7187 unsigned Size = Ty.getSizeInBits();
7189 if (
Size % NarrowSize != 0)
7192 unsigned NumParts =
Size / NarrowSize;
7193 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7194 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7200 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7204 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7205 MI.eraseFromParent();
7215 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7218 LLT SrcTy = MRI.getType(Src);
7229 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7242 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7245 if (SizeOp1 % NarrowSize != 0)
7247 int NumParts = SizeOp1 / NarrowSize;
7250 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7254 uint64_t OpStart =
MI.getOperand(2).getImm();
7255 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7256 for (
int i = 0; i < NumParts; ++i) {
7257 unsigned SrcStart = i * NarrowSize;
7259 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7262 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7270 int64_t ExtractOffset;
7272 if (OpStart < SrcStart) {
7274 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7276 ExtractOffset = OpStart - SrcStart;
7277 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7281 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7283 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7284 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7291 if (MRI.getType(DstReg).isVector())
7292 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7293 else if (DstRegs.
size() > 1)
7294 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7297 MI.eraseFromParent();
7309 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7311 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7314 SrcRegs.
append(LeftoverRegs);
7318 uint64_t OpStart =
MI.getOperand(3).getImm();
7319 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7320 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7321 unsigned DstStart =
I * NarrowSize;
7323 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7331 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7333 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7337 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7345 int64_t ExtractOffset, InsertOffset;
7347 if (OpStart < DstStart) {
7349 ExtractOffset = DstStart - OpStart;
7350 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7352 InsertOffset = OpStart - DstStart;
7355 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7359 if (ExtractOffset != 0 || SegSize != OpSize) {
7361 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7362 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7365 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7366 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7374 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7377 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7379 MI.eraseFromParent();
7387 LLT DstTy = MRI.getType(DstReg);
7389 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7395 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7396 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7400 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7401 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7404 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7405 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7406 {Src0Regs[I], Src1Regs[I]});
7410 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7413 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7414 DstLeftoverRegs.
push_back(Inst.getReg(0));
7417 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7418 LeftoverTy, DstLeftoverRegs);
7420 MI.eraseFromParent();
7430 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7432 LLT DstTy = MRI.getType(DstReg);
7437 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7438 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7439 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7441 MI.eraseFromParent();
7451 Register CondReg =
MI.getOperand(1).getReg();
7452 LLT CondTy = MRI.getType(CondReg);
7457 LLT DstTy = MRI.getType(DstReg);
7463 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7464 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7468 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7469 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7472 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7474 CondReg, Src1Regs[
I], Src2Regs[
I]);
7478 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7480 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7484 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7485 LeftoverTy, DstLeftoverRegs);
7487 MI.eraseFromParent();
7497 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7500 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7501 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7504 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7506 auto C_0 =
B.buildConstant(NarrowTy, 0);
7508 UnmergeSrc.getReg(1), C_0);
7509 auto LoCTLZ = IsUndef ?
7510 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7511 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7512 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7513 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7514 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7515 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7517 MI.eraseFromParent();
7530 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7533 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7534 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7537 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7539 auto C_0 =
B.buildConstant(NarrowTy, 0);
7541 UnmergeSrc.getReg(0), C_0);
7542 auto HiCTTZ = IsUndef ?
7543 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7544 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7545 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7546 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7547 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7548 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7550 MI.eraseFromParent();
7563 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7566 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7571 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7575 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7576 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7578 auto LoSign =
B.buildAShr(NarrowTy,
Lo, ShAmt);
7580 LoSign.getReg(0), Sign.getReg(0));
7585 auto LoCTLS =
B.buildCTLS(DstTy,
Lo);
7586 auto GNarrowSize =
B.buildConstant(DstTy, NarrowSize);
7587 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLS, GNarrowSize);
7591 auto GNarrowSizeMinus1 =
B.buildConstant(DstTy, NarrowSize - 1);
7593 B.buildSelect(DstTy, LoSameSign, HiIsSignCTLS, GNarrowSizeMinus1);
7595 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7597 B.buildSelect(DstReg, HiIsSign, HiSignResult, HiCTLS);
7599 MI.eraseFromParent();
7609 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7612 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7613 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7615 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7616 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7617 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7619 MI.eraseFromParent();
7634 LLT ExpTy = MRI.getType(ExpReg);
7639 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7640 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7641 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7642 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7644 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7646 MI.getOperand(2).setReg(Trunc.getReg(0));
7653 unsigned Opc =
MI.getOpcode();
7656 auto QAction = LI.getAction(Q).Action;
7662 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7665 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7669 case TargetOpcode::G_CTLZ: {
7670 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7671 unsigned Len = SrcTy.getScalarSizeInBits();
7673 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7675 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7676 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7679 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7680 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7681 MI.eraseFromParent();
7697 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7698 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7701 Op = MIBOp.getReg(0);
7706 MI.eraseFromParent();
7709 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7712 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7716 case TargetOpcode::G_CTTZ: {
7717 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7719 unsigned Len = SrcTy.getScalarSizeInBits();
7720 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7723 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7724 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7727 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7728 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7729 MI.eraseFromParent();
7736 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7737 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7739 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7740 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7741 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7742 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7745 MI.eraseFromParent();
7749 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7750 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7754 case TargetOpcode::G_CTPOP: {
7756 LLT Ty = MRI.getType(SrcReg);
7757 unsigned Size = Ty.getScalarSizeInBits();
7769 auto C_1 =
B.buildConstant(Ty, 1);
7770 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7772 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7773 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7774 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7778 auto C_2 =
B.buildConstant(Ty, 2);
7779 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7781 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7782 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7783 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7784 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7791 auto C_4 =
B.buildConstant(Ty, 4);
7792 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7793 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7795 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7796 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7798 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7804 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7806 auto IsMulSupported = [
this](
const LLT Ty) {
7807 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7810 if (IsMulSupported(Ty)) {
7811 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7812 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7814 auto ResTmp = B8Count;
7815 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7816 auto ShiftC =
B.buildConstant(Ty, Shift);
7817 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7818 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7820 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7822 MI.eraseFromParent();
7825 case TargetOpcode::G_CTLS: {
7826 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7830 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
7831 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
7833 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
7839 MI.eraseFromParent();
7860 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7861 LLT Ty = MRI.getType(Dst);
7862 LLT ShTy = MRI.getType(Z);
7869 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7870 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7875 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7876 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7880 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7893 MI.eraseFromParent();
7899 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7900 LLT Ty = MRI.getType(Dst);
7901 LLT ShTy = MRI.getType(Z);
7904 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7914 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7915 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7916 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7917 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7918 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7922 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7925 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7928 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7930 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7931 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7932 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7935 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7937 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7939 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7942 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7943 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7948 MI.eraseFromParent();
7959 LLT Ty = MRI.getType(Dst);
7960 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7962 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7963 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7966 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7967 return lowerFunnelShiftAsShifts(
MI);
7971 if (Result == UnableToLegalize)
7972 return lowerFunnelShiftAsShifts(
MI);
7977 auto [Dst, Src] =
MI.getFirst2Regs();
7978 LLT DstTy = MRI.getType(Dst);
7979 LLT SrcTy = MRI.getType(Src);
7983 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7991 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7995 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7999 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8004 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8005 {UnmergeSrc.getReg(0)});
8006 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8007 {UnmergeSrc.getReg(1)});
8010 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8012 MI.eraseFromParent();
8029 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8033 LLT DstTy = MRI.getType(DstReg);
8034 LLT SrcTy = MRI.getType(SrcReg);
8042 SrcTy.getElementCount().divideCoefficientBy(2));
8055 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8067 MI.eraseFromParent();
8076 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8077 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8078 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8079 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8080 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8081 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8082 MI.eraseFromParent();
8087 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8089 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8090 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8095 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8096 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8098 return lowerRotateWithReverseRotate(
MI);
8101 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8102 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8103 bool IsFShLegal =
false;
8104 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8105 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8109 MI.eraseFromParent();
8114 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8117 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8122 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8123 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8124 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8130 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8131 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8133 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8139 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8140 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8142 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8144 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8149 MI.eraseFromParent();
8157 auto [Dst, Src] =
MI.getFirst2Regs();
8162 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8190 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8203 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8207 MI.eraseFromParent();
8215 auto [Dst, Src] =
MI.getFirst2Regs();
8220 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8233 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8235 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8240 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8242 MI.eraseFromParent();
8250 auto [Dst, Src] =
MI.getFirst2Regs();
8254 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8265 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8266 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8268 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8275 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8276 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8277 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8279 MI.eraseFromParent();
8289 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8295 MI.eraseFromParent();
8300 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8303 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8304 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8305 MIRBuilder.buildSelect(Dst, Src, True, False);
8306 MI.eraseFromParent();
8310 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8330 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8337 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8338 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8339 MIRBuilder.buildSelect(Dst, Src, True, False);
8340 MI.eraseFromParent();
8344 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8367 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8368 MI.eraseFromParent();
8376 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8380 if (SrcTy !=
S64 && SrcTy !=
S32)
8382 if (DstTy !=
S32 && DstTy !=
S64)
8409 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8411 MI.eraseFromParent();
8416 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8421 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8428 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8430 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8431 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8433 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8434 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8436 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8438 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8439 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8440 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8443 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8444 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8445 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8447 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8450 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8455 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8456 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8462 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8464 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8465 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8467 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8472 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8473 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8475 MI.eraseFromParent();
8481 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8483 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8484 unsigned SatWidth = DstTy.getScalarSizeInBits();
8488 APInt MinInt, MaxInt;
8511 if (AreExactFloatBounds) {
8513 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8515 SrcTy.changeElementSize(1), Src, MaxC);
8516 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8518 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8528 MI.eraseFromParent();
8533 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8535 DstTy.changeElementSize(1), Src, Src);
8538 MI.eraseFromParent();
8545 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8554 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8565 MI.eraseFromParent();
8571 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8573 DstTy.changeElementSize(1), Src, Src);
8575 MI.eraseFromParent();
8585 auto [Dst, Src] =
MI.getFirst2Regs();
8587 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8589 if (MRI.getType(Src).isVector())
8593 unsigned Flags =
MI.getFlags();
8596 MI.eraseFromParent();
8600 const unsigned ExpMask = 0x7ff;
8601 const unsigned ExpBiasf64 = 1023;
8602 const unsigned ExpBiasf16 = 15;
8631 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8691 MI.eraseFromParent();
8697 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8701 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8708 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8709 LLT Ty = MRI.getType(Dst);
8711 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8712 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8713 MI.eraseFromParent();
8719 case TargetOpcode::G_SMIN:
8721 case TargetOpcode::G_SMAX:
8723 case TargetOpcode::G_UMIN:
8725 case TargetOpcode::G_UMAX:
8733 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8738 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8739 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8741 MI.eraseFromParent();
8750 LLT DstTy = MRI.getType(Dst);
8751 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8761 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8762 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8764 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8767 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8768 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8769 if (TLI.preferSelectsOverBooleanArithmetic(
8772 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8773 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8775 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8776 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8782 unsigned BoolExtOp =
8784 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8785 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8789 MI.eraseFromParent();
8795 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8796 const int Src0Size = Src0Ty.getScalarSizeInBits();
8797 const int Src1Size = Src1Ty.getScalarSizeInBits();
8802 auto NotSignBitMask =
MIRBuilder.buildConstant(
8807 if (Src0Ty == Src1Ty) {
8808 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8809 }
else if (Src0Size > Src1Size) {
8810 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8811 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8812 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8813 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8815 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8816 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8817 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8818 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8824 unsigned Flags =
MI.getFlags();
8831 MI.eraseFromParent();
8842 switch (
MI.getOpcode()) {
8843 case TargetOpcode::G_FMINNUM:
8844 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8846 case TargetOpcode::G_FMINIMUMNUM:
8847 NewOp = TargetOpcode::G_FMINNUM;
8849 case TargetOpcode::G_FMAXNUM:
8850 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8852 case TargetOpcode::G_FMAXIMUMNUM:
8853 NewOp = TargetOpcode::G_FMAXNUM;
8859 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8860 LLT Ty = MRI.getType(Dst);
8870 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8873 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8878 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8879 MI.eraseFromParent();
8885 unsigned Opc =
MI.getOpcode();
8886 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8887 LLT Ty = MRI.getType(Dst);
8890 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
8892 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
8893 unsigned OpcNonIeee =
8894 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
8895 bool MinMaxMustRespectOrderedZero =
false;
8899 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
8901 MinMaxMustRespectOrderedZero =
true;
8902 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
8907 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
8915 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
8919 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
8921 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
8931 const unsigned Flags =
MI.getFlags();
8937 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
8939 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
8941 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
8943 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
8945 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
8950 MI.eraseFromParent();
8957 LLT Ty = MRI.getType(DstReg);
8958 unsigned Flags =
MI.getFlags();
8963 MI.eraseFromParent();
8969 auto [DstReg,
X] =
MI.getFirst2Regs();
8970 const unsigned Flags =
MI.getFlags();
8971 const LLT Ty = MRI.getType(DstReg);
8983 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8985 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8990 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8991 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8992 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8993 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8995 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8997 MI.eraseFromParent();
9002 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9003 unsigned Flags =
MI.getFlags();
9004 LLT Ty = MRI.getType(DstReg);
9011 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9012 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9015 SrcReg, Zero, Flags);
9017 SrcReg, Trunc, Flags);
9021 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9022 MI.eraseFromParent();
9028 const unsigned NumOps =
MI.getNumOperands();
9029 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9030 unsigned PartSize = Src0Ty.getSizeInBits();
9035 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9036 const unsigned Offset = (
I - 1) * PartSize;
9039 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9042 MRI.createGenericVirtualRegister(WideTy);
9045 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9046 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9047 ResultReg = NextResult;
9050 if (DstTy.isPointer()) {
9051 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9052 DstTy.getAddressSpace())) {
9060 MI.eraseFromParent();
9066 const unsigned NumDst =
MI.getNumOperands() - 1;
9067 Register SrcReg =
MI.getOperand(NumDst).getReg();
9068 Register Dst0Reg =
MI.getOperand(0).getReg();
9069 LLT DstTy = MRI.getType(Dst0Reg);
9078 LLT IntTy = MRI.getType(SrcReg);
9083 unsigned Offset = DstSize;
9084 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9086 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9090 MI.eraseFromParent();
9109 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9110 InsertVal =
MI.getOperand(2).getReg();
9112 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9114 LLT VecTy = MRI.getType(SrcVec);
9124 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9125 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9127 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9130 MI.eraseFromParent();
9135 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9146 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9153 int64_t
Offset = IdxVal * EltBytes;
9164 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9167 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9169 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9172 MI.eraseFromParent();
9178 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9179 MI.getFirst3RegLLTs();
9189 for (
int Idx : Mask) {
9191 if (!Undef.isValid())
9192 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
9197 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9199 int NumElts = Src0Ty.getNumElements();
9200 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9201 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9202 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9204 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9206 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9211 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9212 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9213 MI.eraseFromParent();
9219 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9220 MI.getFirst4RegLLTs();
9222 if (VecTy.isScalableVector())
9238 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9241 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9244 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9247 std::optional<APInt> PassthruSplatVal =
9250 if (PassthruSplatVal.has_value()) {
9252 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9253 }
else if (HasPassthru) {
9254 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9255 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9261 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9265 unsigned NumElmts = VecTy.getNumElements();
9266 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9268 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9271 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9274 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9279 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9281 if (HasPassthru &&
I == NumElmts - 1) {
9284 auto AllLanesSelected =
MIRBuilder.buildICmp(
9286 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9287 {OutPos, EndOfVector});
9291 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9293 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9298 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9300 MI.eraseFromParent();
9311 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9317 if (Alignment >
Align(1)) {
9320 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9329 const auto &MF = *
MI.getMF();
9335 Register AllocSize =
MI.getOperand(1).getReg();
9338 LLT PtrTy = MRI.getType(Dst);
9339 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9346 MI.eraseFromParent();
9352 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9357 MI.eraseFromParent();
9363 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9368 MI.eraseFromParent();
9374 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9375 unsigned Offset =
MI.getOperand(2).getImm();
9378 if (SrcTy.isVector()) {
9379 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9380 unsigned DstSize = DstTy.getSizeInBits();
9382 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9383 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9385 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9389 for (
unsigned Idx =
Offset / SrcEltSize;
9390 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9391 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9393 if (SubVectorElts.
size() == 1)
9394 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9396 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9398 MI.eraseFromParent();
9403 if (DstTy.isScalar() &&
9404 (SrcTy.isScalar() ||
9405 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9406 LLT SrcIntTy = SrcTy;
9407 if (!SrcTy.isScalar()) {
9409 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9416 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9420 MI.eraseFromParent();
9428 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9431 LLT DstTy = MRI.getType(Src);
9432 LLT InsertTy = MRI.getType(InsertSrc);
9440 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9442 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9446 for (; Idx <
Offset / EltSize; ++Idx) {
9447 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9452 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9453 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9455 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9464 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9467 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9468 MI.eraseFromParent();
9482 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9486 LLT IntDstTy = DstTy;
9490 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9495 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9501 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9507 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9508 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9509 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9512 MI.eraseFromParent();
9518 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9519 MI.getFirst4RegLLTs();
9520 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9523 LLT BoolTy = Dst1Ty;
9525 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9542 auto ResultLowerThanLHS =
9547 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9550 MI.eraseFromParent();
9556 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9557 const LLT Ty = MRI.getType(Res);
9560 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9561 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9562 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9573 MI.eraseFromParent();
9578 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9579 const LLT Ty = MRI.getType(Res);
9582 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9583 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9584 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9589 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9594 MI.eraseFromParent();
9600 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9601 LLT Ty = MRI.getType(Res);
9605 switch (
MI.getOpcode()) {
9608 case TargetOpcode::G_UADDSAT:
9611 BaseOp = TargetOpcode::G_ADD;
9613 case TargetOpcode::G_SADDSAT:
9616 BaseOp = TargetOpcode::G_ADD;
9618 case TargetOpcode::G_USUBSAT:
9621 BaseOp = TargetOpcode::G_SUB;
9623 case TargetOpcode::G_SSUBSAT:
9626 BaseOp = TargetOpcode::G_SUB;
9641 uint64_t NumBits = Ty.getScalarSizeInBits();
9652 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9660 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9665 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9666 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9669 MI.eraseFromParent();
9675 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9676 LLT Ty = MRI.getType(Res);
9680 unsigned OverflowOp;
9681 switch (
MI.getOpcode()) {
9684 case TargetOpcode::G_UADDSAT:
9687 OverflowOp = TargetOpcode::G_UADDO;
9689 case TargetOpcode::G_SADDSAT:
9692 OverflowOp = TargetOpcode::G_SADDO;
9694 case TargetOpcode::G_USUBSAT:
9697 OverflowOp = TargetOpcode::G_USUBO;
9699 case TargetOpcode::G_SSUBSAT:
9702 OverflowOp = TargetOpcode::G_SSUBO;
9707 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9708 Register Tmp = OverflowRes.getReg(0);
9709 Register Ov = OverflowRes.getReg(1);
9718 uint64_t NumBits = Ty.getScalarSizeInBits();
9719 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9720 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9723 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9731 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9735 MI.eraseFromParent();
9741 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9742 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9743 "Expected shlsat opcode!");
9744 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9745 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9746 LLT Ty = MRI.getType(Res);
9750 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9751 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9760 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9765 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9767 MI.eraseFromParent();
9772 auto [Dst, Src] =
MI.getFirst2Regs();
9773 const LLT Ty = MRI.getType(Src);
9774 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9775 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9778 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9779 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9780 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9781 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9784 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9786 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9787 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9788 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9790 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9791 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9792 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9794 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9795 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9796 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9798 Res.getInstr()->getOperand(0).setReg(Dst);
9800 MI.eraseFromParent();
9807 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9810 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9811 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9812 return B.buildOr(Dst,
LHS,
RHS);
9817 auto [Dst, Src] =
MI.getFirst2Regs();
9818 const LLT SrcTy = MRI.getType(Src);
9819 unsigned Size = SrcTy.getScalarSizeInBits();
9820 unsigned VSize = SrcTy.getSizeInBits();
9823 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9824 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9825 {LLT::fixed_vector(VSize / 8, 8),
9826 LLT::fixed_vector(VSize / 8, 8)}}))) {
9831 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9832 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9833 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9837 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9860 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9864 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9867 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9871 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9875 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9880 MI.eraseFromParent();
9888 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9889 int NameOpIdx = IsRead ? 1 : 0;
9890 int ValRegIndex = IsRead ? 0 : 1;
9892 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9893 const LLT Ty = MRI.getType(ValReg);
9895 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9902 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9903 Fn,
MI.getDebugLoc()));
9907 MI.eraseFromParent();
9916 MI.eraseFromParent();
9922 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9923 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9925 LLT OrigTy = MRI.getType(Result);
9929 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9930 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9932 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9934 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9935 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9938 MI.eraseFromParent();
9944 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9949 MI.eraseFromParent();
9954 MI.eraseFromParent();
9961 unsigned BitSize = SrcTy.getScalarSizeInBits();
9965 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9971 APInt ExpMask = Inf;
9977 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9978 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9979 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9980 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9981 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9983 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9987 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9989 LLT DstTyCopy = DstTy;
9991 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10019 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10022 Mask &= ~PartialCheck;
10031 else if (PartialCheck ==
fcZero)
10043 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10044 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10045 auto SubnormalRes =
10047 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10049 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10050 appendToRes(SubnormalRes);
10057 else if (PartialCheck ==
fcInf)
10062 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10069 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10070 if (PartialCheck ==
fcNan) {
10074 }
else if (PartialCheck ==
fcQNan) {
10084 Abs, InfWithQnanBitC);
10085 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10092 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10094 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10095 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10098 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10100 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10103 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10104 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10106 appendToRes(NormalRes);
10110 MI.eraseFromParent();
10116 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10117 MI.getFirst4RegLLTs();
10119 bool IsEltPtr = DstTy.isPointerOrPointerVector();
10123 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10124 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10128 if (MaskTy.isScalar()) {
10136 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10140 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
10142 if (DstTy.isVector()) {
10144 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
10145 MaskReg = ShufSplat.getReg(0);
10150 }
else if (!DstTy.isVector()) {
10155 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10159 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10160 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10161 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10168 MI.eraseFromParent();
10174 unsigned Opcode =
MI.getOpcode();
10177 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10178 : TargetOpcode::G_UDIV,
10179 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10181 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10182 : TargetOpcode::G_UREM,
10183 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10184 MI.eraseFromParent();
10194 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10198 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10201 MI.eraseFromParent();
10211 Register SrcReg =
MI.getOperand(1).getReg();
10212 LLT Ty = MRI.getType(SrcReg);
10213 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10216 MI.eraseFromParent();
10222 Register SrcReg =
MI.getOperand(1).getReg();
10223 Register DestReg =
MI.getOperand(0).getReg();
10225 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10226 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10229 MI.eraseFromParent();
10235 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10236 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10237 "Expected G_ABDS or G_ABDU instruction");
10239 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10240 LLT Ty = MRI.getType(LHS);
10250 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10252 MI.eraseFromParent();
10258 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10259 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10260 "Expected G_ABDS or G_ABDU instruction");
10262 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10263 LLT Ty = MRI.getType(LHS);
10268 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10269 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10270 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10272 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10273 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10275 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10277 MI.eraseFromParent();
10282 Register SrcReg =
MI.getOperand(1).getReg();
10283 Register DstReg =
MI.getOperand(0).getReg();
10285 LLT Ty = MRI.getType(DstReg);
10293 MI.eraseFromParent();
10299 Register SrcReg =
MI.getOperand(1).getReg();
10300 LLT SrcTy = MRI.getType(SrcReg);
10301 LLT DstTy = MRI.getType(SrcReg);
10304 if (SrcTy.isScalar()) {
10309 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10320 Register ListPtr =
MI.getOperand(1).getReg();
10321 LLT PtrTy = MRI.getType(ListPtr);
10328 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10330 const Align A(
MI.getOperand(2).getImm());
10332 if (
A > TLI.getMinStackArgumentAlignment()) {
10334 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10335 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10336 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10337 VAList = AndDst.getReg(0);
10344 LLT LLTTy = MRI.getType(Dst);
10347 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10348 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10353 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10355 Align EltAlignment =
DL.getABITypeAlign(Ty);
10358 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10360 MI.eraseFromParent();
10375 unsigned Limit,
const MemOp &
Op,
10376 unsigned DstAS,
unsigned SrcAS,
10377 const AttributeList &FuncAttributes,
10379 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10389 if (
Op.isFixedDstAlign())
10390 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10393 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10397 unsigned NumMemOps = 0;
10400 unsigned TySize = Ty.getSizeInBytes();
10401 while (TySize >
Size) {
10410 assert(NewTySize > 0 &&
"Could not find appropriate type");
10417 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10419 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10425 TySize = NewTySize;
10429 if (++NumMemOps > Limit)
10432 MemOps.push_back(Ty);
10442 unsigned NumBits = Ty.getScalarSizeInBits();
10444 if (!Ty.isVector() && ValVRegAndVal) {
10445 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10453 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10474 uint64_t KnownLen,
Align Alignment,
10476 auto &MF = *
MI.getParent()->getParent();
10481 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10483 bool DstAlignCanChange =
false;
10487 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10489 DstAlignCanChange =
true;
10491 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10492 std::vector<LLT> MemOps;
10494 const auto &DstMMO = **
MI.memoperands_begin();
10495 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10498 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10509 if (DstAlignCanChange) {
10512 Align NewAlign =
DL.getABITypeAlign(IRTy);
10513 if (NewAlign > Alignment) {
10514 Alignment = NewAlign;
10522 MachineIRBuilder MIB(
MI);
10524 LLT LargestTy = MemOps[0];
10525 for (
unsigned i = 1; i < MemOps.size(); i++)
10527 LargestTy = MemOps[i];
10539 LLT PtrTy = MRI.getType(Dst);
10540 unsigned DstOff = 0;
10541 unsigned Size = KnownLen;
10542 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10543 LLT Ty = MemOps[
I];
10545 if (TySize >
Size) {
10548 assert(
I == MemOps.size() - 1 &&
I != 0);
10549 DstOff -= TySize -
Size;
10559 TLI.isTruncateFree(LargestVT, VT))
10560 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10573 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10576 MIB.buildStore(
Value, Ptr, *StoreMMO);
10581 MI.eraseFromParent();
10587 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10589 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10591 const auto *MMOIt =
MI.memoperands_begin();
10593 bool IsVolatile =
MemOp->isVolatile();
10599 "inline memcpy with dynamic size is not yet supported");
10600 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10601 if (KnownLen == 0) {
10602 MI.eraseFromParent();
10606 const auto &DstMMO = **
MI.memoperands_begin();
10607 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10608 Align DstAlign = DstMMO.getBaseAlign();
10609 Align SrcAlign = SrcMMO.getBaseAlign();
10611 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10618 Align SrcAlign,
bool IsVolatile) {
10619 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10620 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10621 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10628 Align SrcAlign,
bool IsVolatile) {
10629 auto &MF = *
MI.getParent()->getParent();
10634 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10636 bool DstAlignCanChange =
false;
10638 Align Alignment = std::min(DstAlign, SrcAlign);
10642 DstAlignCanChange =
true;
10648 std::vector<LLT> MemOps;
10650 const auto &DstMMO = **
MI.memoperands_begin();
10651 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10657 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10663 if (DstAlignCanChange) {
10666 Align NewAlign =
DL.getABITypeAlign(IRTy);
10671 if (!
TRI->hasStackRealignment(MF))
10673 NewAlign = std::min(NewAlign, *StackAlign);
10675 if (NewAlign > Alignment) {
10676 Alignment = NewAlign;
10684 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10686 MachineIRBuilder MIB(
MI);
10692 unsigned CurrOffset = 0;
10693 unsigned Size = KnownLen;
10694 for (
auto CopyTy : MemOps) {
10697 if (CopyTy.getSizeInBytes() >
Size)
10698 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10709 if (CurrOffset != 0) {
10710 LLT SrcTy = MRI.getType(Src);
10713 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10715 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10719 if (CurrOffset != 0) {
10720 LLT DstTy = MRI.getType(Dst);
10721 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10723 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10724 CurrOffset += CopyTy.getSizeInBytes();
10725 Size -= CopyTy.getSizeInBytes();
10728 MI.eraseFromParent();
10734 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10736 auto &MF = *
MI.getParent()->getParent();
10741 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10743 bool DstAlignCanChange =
false;
10746 Align Alignment = std::min(DstAlign, SrcAlign);
10748 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10750 DstAlignCanChange =
true;
10752 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10753 std::vector<LLT> MemOps;
10755 const auto &DstMMO = **
MI.memoperands_begin();
10756 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10757 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10758 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10765 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10771 if (DstAlignCanChange) {
10774 Align NewAlign =
DL.getABITypeAlign(IRTy);
10779 if (!
TRI->hasStackRealignment(MF))
10780 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10781 NewAlign = std::min(NewAlign, *StackAlign);
10783 if (NewAlign > Alignment) {
10784 Alignment = NewAlign;
10792 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10794 MachineIRBuilder MIB(
MI);
10798 unsigned CurrOffset = 0;
10799 SmallVector<Register, 16> LoadVals;
10800 for (
auto CopyTy : MemOps) {
10807 if (CurrOffset != 0) {
10808 LLT SrcTy = MRI.getType(Src);
10811 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10813 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10814 CurrOffset += CopyTy.getSizeInBytes();
10818 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10819 LLT CopyTy = MemOps[
I];
10825 if (CurrOffset != 0) {
10826 LLT DstTy = MRI.getType(Dst);
10829 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10831 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10834 MI.eraseFromParent();
10840 const unsigned Opc =
MI.getOpcode();
10843 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10844 Opc == TargetOpcode::G_MEMSET) &&
10845 "Expected memcpy like instruction");
10847 auto MMOIt =
MI.memoperands_begin();
10852 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10854 if (
Opc != TargetOpcode::G_MEMSET) {
10855 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10856 MemOp = *(++MMOIt);
10857 SrcAlign =
MemOp->getBaseAlign();
10862 if (!LenVRegAndVal)
10864 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10866 if (KnownLen == 0) {
10867 MI.eraseFromParent();
10871 if (MaxLen && KnownLen > MaxLen)
10874 bool IsVolatile =
MemOp->isVolatile();
10875 if (
Opc == TargetOpcode::G_MEMCPY) {
10876 auto &MF = *
MI.getParent()->getParent();
10879 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10880 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10883 if (
Opc == TargetOpcode::G_MEMMOVE)
10884 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10885 if (
Opc == TargetOpcode::G_MEMSET)
10886 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 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 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.
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 narrowScalarCTLS(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
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 LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B, const LibcallLoweringInfo *Libcalls=nullptr)
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 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 LegalizeResult conversionLibcall(MachineInstr &MI, Type *ToType, Type *FromType, LostDebugLocObserver &LocObserver, bool IsSigned=false) const
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 createMemLibcall(MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver) const
Create a libcall to memcpy et al.
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 createLibcall(const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr) const
Helper function that creates a libcall to the given Name using the given calling convention CC.
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 simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver) const
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)
Tracks which library functions to use for a particular subtarget.
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
StringRef - Represent a constant reference to a string, i.e.
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
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...
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)
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)
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.