44#define DEBUG_TYPE "legalizer"
57static std::pair<int, int>
63 unsigned NumParts =
Size / NarrowSize;
64 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
67 if (LeftoverSize == 0)
72 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
130 auto Step = LI.getAction(
MI, MRI);
131 switch (Step.Action) {
146 return bitcast(
MI, Step.TypeIdx, Step.NewType);
149 return lower(
MI, Step.TypeIdx, Step.NewType);
158 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
166void LegalizerHelper::insertParts(
Register DstReg,
188 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
190 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
191 return mergeMixedSubvectors(DstReg, AllRegs);
197 extractGCDType(GCDRegs, GCDTy, PartReg);
198 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
199 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
204 LLT Ty = MRI.getType(
Reg);
212void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
215 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
216 appendVectorElts(AllElts, PartRegs[i]);
219 if (!MRI.getType(Leftover).isVector())
222 appendVectorElts(AllElts, Leftover);
224 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
230 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
232 const int StartIdx = Regs.
size();
233 const int NumResults =
MI.getNumOperands() - 1;
235 for (
int I = 0;
I != NumResults; ++
I)
236 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
241 LLT SrcTy = MRI.getType(SrcReg);
242 if (SrcTy == GCDTy) {
248 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
255 LLT SrcTy = MRI.getType(SrcReg);
257 extractGCDType(Parts, GCDTy, SrcReg);
261LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
263 unsigned PadStrategy) {
268 int NumOrigSrc = VRegs.
size();
274 if (NumOrigSrc < NumParts * NumSubParts) {
275 if (PadStrategy == TargetOpcode::G_ZEXT)
276 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
277 else if (PadStrategy == TargetOpcode::G_ANYEXT)
278 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
280 assert(PadStrategy == TargetOpcode::G_SEXT);
285 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
301 for (
int I = 0;
I != NumParts; ++
I) {
302 bool AllMergePartsArePadding =
true;
305 for (
int J = 0; J != NumSubParts; ++J) {
306 int Idx =
I * NumSubParts + J;
307 if (Idx >= NumOrigSrc) {
308 SubMerge[J] = PadReg;
312 SubMerge[J] = VRegs[Idx];
315 AllMergePartsArePadding =
false;
321 if (AllMergePartsArePadding && !AllPadReg) {
322 if (PadStrategy == TargetOpcode::G_ANYEXT)
323 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
324 else if (PadStrategy == TargetOpcode::G_ZEXT)
325 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
334 Remerge[
I] = AllPadReg;
338 if (NumSubParts == 1)
339 Remerge[
I] = SubMerge[0];
341 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
344 if (AllMergePartsArePadding && !AllPadReg)
345 AllPadReg = Remerge[
I];
348 VRegs = std::move(Remerge);
352void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
354 LLT DstTy = MRI.getType(DstReg);
359 if (DstTy == LCMTy) {
360 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
364 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
373 UnmergeDefs[0] = DstReg;
374 for (
unsigned I = 1;
I != NumDefs; ++
I)
375 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
378 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
386#define RTLIBCASE_INT(LibcallPrefix) \
390 return RTLIB::LibcallPrefix##32; \
392 return RTLIB::LibcallPrefix##64; \
394 return RTLIB::LibcallPrefix##128; \
396 llvm_unreachable("unexpected size"); \
400#define RTLIBCASE(LibcallPrefix) \
404 return RTLIB::LibcallPrefix##32; \
406 return RTLIB::LibcallPrefix##64; \
408 return RTLIB::LibcallPrefix##80; \
410 return RTLIB::LibcallPrefix##128; \
412 llvm_unreachable("unexpected size"); \
417 case TargetOpcode::G_LROUND:
419 case TargetOpcode::G_LLROUND:
421 case TargetOpcode::G_MUL:
423 case TargetOpcode::G_SDIV:
425 case TargetOpcode::G_UDIV:
427 case TargetOpcode::G_SREM:
429 case TargetOpcode::G_UREM:
431 case TargetOpcode::G_CTLZ_ZERO_POISON:
433 case TargetOpcode::G_FADD:
435 case TargetOpcode::G_FSUB:
437 case TargetOpcode::G_FMUL:
439 case TargetOpcode::G_FDIV:
441 case TargetOpcode::G_FEXP:
443 case TargetOpcode::G_FEXP2:
445 case TargetOpcode::G_FEXP10:
447 case TargetOpcode::G_FREM:
449 case TargetOpcode::G_FPOW:
451 case TargetOpcode::G_FPOWI:
453 case TargetOpcode::G_FMA:
455 case TargetOpcode::G_FSIN:
457 case TargetOpcode::G_FCOS:
459 case TargetOpcode::G_FTAN:
461 case TargetOpcode::G_FASIN:
463 case TargetOpcode::G_FACOS:
465 case TargetOpcode::G_FATAN:
467 case TargetOpcode::G_FATAN2:
469 case TargetOpcode::G_FSINH:
471 case TargetOpcode::G_FCOSH:
473 case TargetOpcode::G_FTANH:
475 case TargetOpcode::G_FSINCOS:
477 case TargetOpcode::G_FMODF:
479 case TargetOpcode::G_FLOG10:
481 case TargetOpcode::G_FLOG:
483 case TargetOpcode::G_FLOG2:
485 case TargetOpcode::G_FLDEXP:
487 case TargetOpcode::G_FCEIL:
489 case TargetOpcode::G_FFLOOR:
491 case TargetOpcode::G_FMINNUM:
493 case TargetOpcode::G_FMAXNUM:
495 case TargetOpcode::G_FMINIMUMNUM:
497 case TargetOpcode::G_FMAXIMUMNUM:
499 case TargetOpcode::G_FSQRT:
501 case TargetOpcode::G_FRINT:
503 case TargetOpcode::G_FNEARBYINT:
505 case TargetOpcode::G_INTRINSIC_TRUNC:
507 case TargetOpcode::G_INTRINSIC_ROUND:
509 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
511 case TargetOpcode::G_INTRINSIC_LRINT:
513 case TargetOpcode::G_INTRINSIC_LLRINT:
533 AttributeList CallerAttrs =
F.getAttributes();
534 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
535 .removeAttribute(Attribute::NoAlias)
536 .removeAttribute(Attribute::NonNull)
541 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
542 CallerAttrs.hasRetAttr(Attribute::SExt))
553 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
560 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
568 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
571 if (Ret->getNumImplicitOperands() != 1)
574 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
591 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
596 Info.OrigRet = Result;
599 (Result.Ty->isVoidTy() ||
600 Result.Ty ==
MIRBuilder.getMF().getFunction().getReturnType()) &&
608 if (
MI && Info.LoweredTailCall) {
609 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
619 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
620 "Expected instr following MI to be return or debug inst?");
623 Next->eraseFromParent();
624 }
while (
MI->getNextNode());
639 RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(
Libcall);
640 if (LibcallImpl == RTLIB::Unsupported)
644 const CallingConv::ID CC = Libcalls->getLibcallImplCallingConv(LibcallImpl);
658 Args.push_back({MO.getReg(), OpType, 0});
677 unsigned AddrSpace =
DL.getAllocaAddrSpace();
695 if (LibcallResult != LegalizeResult::Legalized)
703 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
704 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
705 MI.eraseFromParent();
720 LLT DstTy = MRI.getType(DstFrac);
725 unsigned AddrSpace =
DL.getAllocaAddrSpace();
726 MachinePointerInfo PtrInfo;
735 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
738 if (LibcallResult != LegalizeResult::Legalized)
744 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
745 MI.eraseFromParent();
756 case TargetOpcode::G_FPEXT:
758 case TargetOpcode::G_FPTRUNC:
760 case TargetOpcode::G_FPTOSI:
762 case TargetOpcode::G_FPTOUI:
764 case TargetOpcode::G_SITOFP:
766 case TargetOpcode::G_UITOFP:
776 if (FromType->isIntegerTy()) {
777 if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
778 Arg.
Flags[0].setSExt();
780 Arg.
Flags[0].setZExt();
791 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
795 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
799 LLT OpLLT = MRI.getType(Reg);
805 Args.push_back({Reg,
OpTy, 0});
808 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
809 RTLIB::Libcall RTLibcall;
810 unsigned Opc =
MI.getOpcode();
812 case TargetOpcode::G_BZERO:
813 RTLibcall = RTLIB::BZERO;
815 case TargetOpcode::G_MEMCPY:
816 RTLibcall = RTLIB::MEMCPY;
817 Args[0].Flags[0].setReturned();
819 case TargetOpcode::G_MEMMOVE:
820 RTLibcall = RTLIB::MEMMOVE;
821 Args[0].Flags[0].setReturned();
823 case TargetOpcode::G_MEMSET:
824 RTLibcall = RTLIB::MEMSET;
825 Args[0].Flags[0].setReturned();
834 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
837 if (RTLibcallImpl == RTLIB::Unsupported) {
844 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
851 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
858 if (Info.LoweredTailCall) {
859 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
869 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
870 "Expected instr following MI to be return or debug inst?");
873 Next->eraseFromParent();
874 }
while (
MI.getNextNode());
884 unsigned Opc =
MI.getOpcode();
886 auto &MMO = AtomicMI.getMMO();
887 auto Ordering = MMO.getMergedOrdering();
888 LLT MemType = MMO.getMemoryType();
891 return RTLIB::UNKNOWN_LIBCALL;
893#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
895 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
897 case TargetOpcode::G_ATOMIC_CMPXCHG:
898 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
899 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
900 return getOutlineAtomicHelper(LC, Ordering, MemSize);
902 case TargetOpcode::G_ATOMICRMW_XCHG: {
903 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
904 return getOutlineAtomicHelper(LC, Ordering, MemSize);
906 case TargetOpcode::G_ATOMICRMW_ADD:
907 case TargetOpcode::G_ATOMICRMW_SUB: {
908 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
909 return getOutlineAtomicHelper(LC, Ordering, MemSize);
911 case TargetOpcode::G_ATOMICRMW_AND: {
912 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
913 return getOutlineAtomicHelper(LC, Ordering, MemSize);
915 case TargetOpcode::G_ATOMICRMW_OR: {
916 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
917 return getOutlineAtomicHelper(LC, Ordering, MemSize);
919 case TargetOpcode::G_ATOMICRMW_XOR: {
920 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
921 return getOutlineAtomicHelper(LC, Ordering, MemSize);
924 return RTLIB::UNKNOWN_LIBCALL;
937 unsigned Opc =
MI.getOpcode();
939 case TargetOpcode::G_ATOMIC_CMPXCHG:
940 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
943 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
944 MI.getFirst4RegLLTs();
947 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
948 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
949 NewLLT) =
MI.getFirst5RegLLTs();
959 case TargetOpcode::G_ATOMICRMW_XCHG:
960 case TargetOpcode::G_ATOMICRMW_ADD:
961 case TargetOpcode::G_ATOMICRMW_SUB:
962 case TargetOpcode::G_ATOMICRMW_AND:
963 case TargetOpcode::G_ATOMICRMW_OR:
964 case TargetOpcode::G_ATOMICRMW_XOR: {
965 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
968 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
972 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
987 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
989 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
992 if (RTLibcallImpl == RTLIB::Unsupported) {
999 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
1013static RTLIB::Libcall
1015 RTLIB::Libcall RTLibcall;
1016 switch (
MI.getOpcode()) {
1017 case TargetOpcode::G_GET_FPENV:
1018 RTLibcall = RTLIB::FEGETENV;
1020 case TargetOpcode::G_SET_FPENV:
1021 case TargetOpcode::G_RESET_FPENV:
1022 RTLibcall = RTLIB::FESETENV;
1024 case TargetOpcode::G_GET_FPMODE:
1025 RTLibcall = RTLIB::FEGETMODE;
1027 case TargetOpcode::G_SET_FPMODE:
1028 case TargetOpcode::G_RESET_FPMODE:
1029 RTLibcall = RTLIB::FESETMODE;
1061 LLT StateTy = MRI.getType(Dst);
1064 MachinePointerInfo TempPtrInfo;
1068 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1073 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
1081 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1099 LLT StateTy = MRI.getType(Src);
1102 MachinePointerInfo TempPtrInfo;
1111 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1116 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1117 LocObserver,
nullptr);
1123static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1125#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1129 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1131 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1133 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1135 llvm_unreachable("unexpected size"); \
1166 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1169 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1176 LLT DstTy = MRI.getType(DstReg);
1177 const auto Cond =
Cmp->getCond();
1182 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1187 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1191 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1198 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1204 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1206 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1219 const auto [OeqLibcall, OeqPred] =
1221 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1223 const auto [UnoLibcall, UnoPred] =
1225 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1240 const auto [OeqLibcall, OeqPred] =
1245 const auto [UnoLibcall, UnoPred] =
1250 if (NotOeq && NotUno)
1269 const auto [InversedLibcall, InversedPred] =
1271 if (!BuildLibcall(InversedLibcall,
1296 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1298 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1301 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1307 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1312 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1314 switch (
MI.getOpcode()) {
1317 case TargetOpcode::G_MUL:
1318 case TargetOpcode::G_SDIV:
1319 case TargetOpcode::G_UDIV:
1320 case TargetOpcode::G_SREM:
1321 case TargetOpcode::G_UREM:
1322 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1323 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1331 case TargetOpcode::G_FADD:
1332 case TargetOpcode::G_FSUB:
1333 case TargetOpcode::G_FMUL:
1334 case TargetOpcode::G_FDIV:
1335 case TargetOpcode::G_FMA:
1336 case TargetOpcode::G_FPOW:
1337 case TargetOpcode::G_FREM:
1338 case TargetOpcode::G_FCOS:
1339 case TargetOpcode::G_FSIN:
1340 case TargetOpcode::G_FTAN:
1341 case TargetOpcode::G_FACOS:
1342 case TargetOpcode::G_FASIN:
1343 case TargetOpcode::G_FATAN:
1344 case TargetOpcode::G_FATAN2:
1345 case TargetOpcode::G_FCOSH:
1346 case TargetOpcode::G_FSINH:
1347 case TargetOpcode::G_FTANH:
1348 case TargetOpcode::G_FLOG10:
1349 case TargetOpcode::G_FLOG:
1350 case TargetOpcode::G_FLOG2:
1351 case TargetOpcode::G_FEXP:
1352 case TargetOpcode::G_FEXP2:
1353 case TargetOpcode::G_FEXP10:
1354 case TargetOpcode::G_FCEIL:
1355 case TargetOpcode::G_FFLOOR:
1356 case TargetOpcode::G_FMINNUM:
1357 case TargetOpcode::G_FMAXNUM:
1358 case TargetOpcode::G_FMINIMUMNUM:
1359 case TargetOpcode::G_FMAXIMUMNUM:
1360 case TargetOpcode::G_FSQRT:
1361 case TargetOpcode::G_FRINT:
1362 case TargetOpcode::G_FNEARBYINT:
1363 case TargetOpcode::G_INTRINSIC_TRUNC:
1364 case TargetOpcode::G_INTRINSIC_ROUND:
1365 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1366 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1370 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1378 case TargetOpcode::G_FSINCOS: {
1379 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1383 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1388 case TargetOpcode::G_FMODF: {
1389 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1393 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1398 case TargetOpcode::G_LROUND:
1399 case TargetOpcode::G_LLROUND:
1400 case TargetOpcode::G_INTRINSIC_LRINT:
1401 case TargetOpcode::G_INTRINSIC_LLRINT: {
1402 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1406 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1408 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1414 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1417 MI.eraseFromParent();
1420 case TargetOpcode::G_FPOWI:
1421 case TargetOpcode::G_FLDEXP: {
1422 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1426 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1428 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1433 {
MI.getOperand(1).getReg(), HLTy, 0},
1434 {
MI.getOperand(2).getReg(), ITy, 1}};
1435 Args[1].Flags[0].setSExt();
1437 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1442 case TargetOpcode::G_FPEXT:
1443 case TargetOpcode::G_FPTRUNC: {
1446 if (!FromTy || !ToTy)
1453 case TargetOpcode::G_FCMP: {
1457 MI.eraseFromParent();
1460 case TargetOpcode::G_FPTOSI:
1461 case TargetOpcode::G_FPTOUI: {
1465 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1466 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1469 FromTy, LocObserver);
1474 case TargetOpcode::G_SITOFP:
1475 case TargetOpcode::G_UITOFP: {
1476 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1479 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1481 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1488 case TargetOpcode::G_ATOMICRMW_XCHG:
1489 case TargetOpcode::G_ATOMICRMW_ADD:
1490 case TargetOpcode::G_ATOMICRMW_SUB:
1491 case TargetOpcode::G_ATOMICRMW_AND:
1492 case TargetOpcode::G_ATOMICRMW_OR:
1493 case TargetOpcode::G_ATOMICRMW_XOR:
1494 case TargetOpcode::G_ATOMIC_CMPXCHG:
1495 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1501 case TargetOpcode::G_BZERO:
1502 case TargetOpcode::G_MEMCPY:
1503 case TargetOpcode::G_MEMMOVE:
1504 case TargetOpcode::G_MEMSET: {
1509 MI.eraseFromParent();
1512 case TargetOpcode::G_GET_FPENV:
1513 case TargetOpcode::G_GET_FPMODE: {
1519 case TargetOpcode::G_SET_FPENV:
1520 case TargetOpcode::G_SET_FPMODE: {
1526 case TargetOpcode::G_RESET_FPENV:
1527 case TargetOpcode::G_RESET_FPMODE: {
1535 MI.eraseFromParent();
1542 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1545 switch (
MI.getOpcode()) {
1548 case TargetOpcode::G_IMPLICIT_DEF: {
1550 LLT DstTy = MRI.getType(DstReg);
1558 if (SizeOp0 % NarrowSize != 0) {
1563 MI.eraseFromParent();
1567 int NumParts = SizeOp0 / NarrowSize;
1570 for (
int i = 0; i < NumParts; ++i)
1574 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1576 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1577 MI.eraseFromParent();
1580 case TargetOpcode::G_CONSTANT: {
1581 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1582 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1583 unsigned TotalSize = Ty.getSizeInBits();
1585 int NumParts = TotalSize / NarrowSize;
1588 for (
int I = 0;
I != NumParts; ++
I) {
1589 unsigned Offset =
I * NarrowSize;
1596 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1598 if (LeftoverBits != 0) {
1602 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1606 insertParts(
MI.getOperand(0).getReg(),
1607 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1609 MI.eraseFromParent();
1612 case TargetOpcode::G_SEXT:
1613 case TargetOpcode::G_ZEXT:
1614 case TargetOpcode::G_ANYEXT:
1616 case TargetOpcode::G_TRUNC: {
1620 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1622 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1626 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1627 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1628 MI.eraseFromParent();
1631 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1632 case TargetOpcode::G_FREEZE: {
1636 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1641 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1643 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1645 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1649 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1650 MI.eraseFromParent();
1653 case TargetOpcode::G_ADD:
1654 case TargetOpcode::G_SUB:
1655 case TargetOpcode::G_SADDO:
1656 case TargetOpcode::G_SSUBO:
1657 case TargetOpcode::G_SADDE:
1658 case TargetOpcode::G_SSUBE:
1659 case TargetOpcode::G_UADDO:
1660 case TargetOpcode::G_USUBO:
1661 case TargetOpcode::G_UADDE:
1662 case TargetOpcode::G_USUBE:
1664 case TargetOpcode::G_MUL:
1665 case TargetOpcode::G_UMULH:
1667 case TargetOpcode::G_EXTRACT:
1669 case TargetOpcode::G_INSERT:
1671 case TargetOpcode::G_LOAD: {
1673 Register DstReg = LoadMI.getDstReg();
1674 LLT DstTy = MRI.getType(DstReg);
1678 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1679 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1680 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1682 LoadMI.eraseFromParent();
1688 case TargetOpcode::G_ZEXTLOAD:
1689 case TargetOpcode::G_SEXTLOAD:
1690 case TargetOpcode::G_FPEXTLOAD: {
1692 Register DstReg = LoadMI.getDstReg();
1693 Register PtrReg = LoadMI.getPointerReg();
1695 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1696 auto &MMO = LoadMI.getMMO();
1699 if (MemSize == NarrowSize) {
1701 }
else if (MemSize < NarrowSize) {
1702 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1703 }
else if (MemSize > NarrowSize) {
1715 LoadMI.eraseFromParent();
1718 case TargetOpcode::G_STORE: {
1721 Register SrcReg = StoreMI.getValueReg();
1722 LLT SrcTy = MRI.getType(SrcReg);
1723 if (SrcTy.isVector())
1726 int NumParts = SizeOp0 / NarrowSize;
1728 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1729 if (SrcTy.isVector() && LeftoverBits != 0)
1732 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1733 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1735 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1736 StoreMI.eraseFromParent();
1742 case TargetOpcode::G_FPTRUNCSTORE: {
1744 Register SrcReg = StoreMI.getValueReg();
1745 Register PtrReg = StoreMI.getPointerReg();
1747 auto &MMO = StoreMI.getMMO();
1749 if (MemSize > NarrowSize) {
1753 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1754 if (MemSize == NarrowSize) {
1756 }
else if (MemSize < NarrowSize) {
1757 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1761 StoreMI.eraseFromParent();
1764 case TargetOpcode::G_SELECT:
1766 case TargetOpcode::G_AND:
1767 case TargetOpcode::G_OR:
1768 case TargetOpcode::G_XOR: {
1780 case TargetOpcode::G_SHL:
1781 case TargetOpcode::G_LSHR:
1782 case TargetOpcode::G_ASHR:
1784 case TargetOpcode::G_CTLZ:
1785 case TargetOpcode::G_CTLZ_ZERO_POISON:
1786 case TargetOpcode::G_CTTZ:
1787 case TargetOpcode::G_CTTZ_ZERO_POISON:
1788 case TargetOpcode::G_CTLS:
1789 case TargetOpcode::G_CTPOP:
1791 switch (
MI.getOpcode()) {
1792 case TargetOpcode::G_CTLZ:
1793 case TargetOpcode::G_CTLZ_ZERO_POISON:
1795 case TargetOpcode::G_CTTZ:
1796 case TargetOpcode::G_CTTZ_ZERO_POISON:
1798 case TargetOpcode::G_CTPOP:
1800 case TargetOpcode::G_CTLS:
1810 case TargetOpcode::G_INTTOPTR:
1818 case TargetOpcode::G_PTRTOINT:
1826 case TargetOpcode::G_PHI: {
1829 if (SizeOp0 % NarrowSize != 0)
1832 unsigned NumParts = SizeOp0 / NarrowSize;
1836 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1844 for (
unsigned i = 0; i < NumParts; ++i) {
1845 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1847 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1848 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1849 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1852 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1854 MI.eraseFromParent();
1857 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1858 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1862 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1868 case TargetOpcode::G_ICMP: {
1870 LLT SrcTy = MRI.getType(LHS);
1876 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1882 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1883 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1889 LLT ResTy = MRI.getType(Dst);
1894 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1896 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1897 auto LHS = std::get<0>(LHSAndRHS);
1898 auto RHS = std::get<1>(LHSAndRHS);
1899 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1906 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1907 auto LHS = std::get<0>(LHSAndRHS);
1908 auto RHS = std::get<1>(LHSAndRHS);
1909 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1910 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1911 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1912 TargetOpcode::G_ZEXT);
1919 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1920 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1921 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1926 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1930 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1935 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1939 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1942 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1945 LHSPartRegs[
I], RHSPartRegs[
I]);
1946 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1952 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1961 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1965 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1966 RHSLeftoverRegs[
I]);
1968 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1969 RHSLeftoverRegs[
I]);
1972 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1973 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1979 MI.eraseFromParent();
1982 case TargetOpcode::G_FCMP:
1991 case TargetOpcode::G_SEXT_INREG: {
1995 int64_t SizeInBits =
MI.getOperand(2).getImm();
2004 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2005 MO1.
setReg(TruncMIB.getReg(0));
2008 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2020 if (SizeOp0 % NarrowSize != 0)
2022 int NumParts = SizeOp0 / NarrowSize;
2030 for (
int i = 0; i < NumParts; ++i) {
2031 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2046 for (
int i = 0; i < NumParts; ++i) {
2049 PartialExtensionReg = DstRegs.
back();
2051 assert(PartialExtensionReg &&
2052 "Expected to visit partial extension before full");
2053 if (FullExtensionReg) {
2058 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2060 FullExtensionReg = DstRegs.
back();
2065 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2068 PartialExtensionReg = DstRegs.
back();
2074 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2075 MI.eraseFromParent();
2078 case TargetOpcode::G_BSWAP:
2079 case TargetOpcode::G_BITREVERSE: {
2080 if (SizeOp0 % NarrowSize != 0)
2085 unsigned NumParts = SizeOp0 / NarrowSize;
2086 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2089 for (
unsigned i = 0; i < NumParts; ++i) {
2090 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2091 {SrcRegs[NumParts - 1 - i]});
2095 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2098 MI.eraseFromParent();
2101 case TargetOpcode::G_PTR_ADD:
2102 case TargetOpcode::G_PTRMASK: {
2110 case TargetOpcode::G_FPTOUI:
2111 case TargetOpcode::G_FPTOSI:
2112 case TargetOpcode::G_FPTOUI_SAT:
2113 case TargetOpcode::G_FPTOSI_SAT:
2115 case TargetOpcode::G_FPEXT:
2122 case TargetOpcode::G_FLDEXP:
2123 case TargetOpcode::G_STRICT_FLDEXP:
2125 case TargetOpcode::G_VSCALE: {
2127 LLT Ty = MRI.getType(Dst);
2131 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2132 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2133 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2136 MI.eraseFromParent();
2143 LLT Ty = MRI.getType(Val);
2149 if (Ty.isPointer()) {
2150 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2152 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2158 if (Ty.isPointerVector())
2159 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2160 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2164 unsigned OpIdx,
unsigned ExtOpcode) {
2166 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2167 MO.
setReg(ExtB.getReg(0));
2173 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2175 MO.
setReg(ExtB.getReg(0));
2181 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2182 MO.
setReg(ExtB.getReg(0));
2186 unsigned OpIdx,
unsigned TruncOpcode) {
2188 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2190 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2197 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2199 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2204 unsigned OpIdx,
unsigned ExtOpcode) {
2206 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2208 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2217 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2219 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2225 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2235 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2242LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2247 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2248 if (DstTy.isVector())
2253 const int SrcSize = SrcTy.getSizeInBits();
2255 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2257 unsigned NumOps =
MI.getNumOperands();
2258 unsigned NumSrc =
MI.getNumOperands() - 1;
2259 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2261 if (WideSize >= DstSize) {
2265 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2266 const unsigned Offset = (
I - 1) * PartSize;
2279 ResultReg = NextResult;
2282 if (WideSize > DstSize)
2284 else if (DstTy.isPointer())
2287 MI.eraseFromParent();
2312 const int GCD = std::gcd(SrcSize, WideSize);
2322 if (GCD == SrcSize) {
2325 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2326 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2332 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2334 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2338 const int PartsPerGCD = WideSize / GCD;
2342 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2344 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2351 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2353 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2354 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2357 MI.eraseFromParent();
2362LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2367 int NumDst =
MI.getNumOperands() - 1;
2368 Register SrcReg =
MI.getOperand(NumDst).getReg();
2369 LLT SrcTy = MRI.getType(SrcReg);
2373 Register Dst0Reg =
MI.getOperand(0).getReg();
2374 LLT DstTy = MRI.getType(Dst0Reg);
2383 dbgs() <<
"Not casting non-integral address space integer\n");
2388 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2396 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2404 for (
int I = 1;
I != NumDst; ++
I) {
2405 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2406 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2410 MI.eraseFromParent();
2421 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2425 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2428 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2446 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2451 if (PartsPerRemerge == 1) {
2454 for (
int I = 0;
I != NumUnmerge; ++
I) {
2455 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2457 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2458 int Idx =
I * PartsPerUnmerge + J;
2460 MIB.addDef(
MI.getOperand(Idx).getReg());
2463 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2467 MIB.addUse(Unmerge.getReg(
I));
2470 SmallVector<Register, 16> Parts;
2471 for (
int J = 0; J != NumUnmerge; ++J)
2472 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2475 for (
int I = 0;
I != NumDst; ++
I) {
2476 for (
int J = 0; J < PartsPerRemerge; ++J) {
2477 const int Idx =
I * PartsPerRemerge + J;
2481 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2482 RemergeParts.
clear();
2486 MI.eraseFromParent();
2491LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2493 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2494 unsigned Offset =
MI.getOperand(2).getImm();
2497 if (SrcTy.
isVector() || DstTy.isVector())
2509 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2513 if (DstTy.isPointer())
2520 MI.eraseFromParent();
2525 LLT ShiftTy = SrcTy;
2534 MI.eraseFromParent();
2565LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2567 if (TypeIdx != 0 || WideTy.
isVector())
2577LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2581 std::optional<Register> CarryIn;
2582 switch (
MI.getOpcode()) {
2585 case TargetOpcode::G_SADDO:
2586 Opcode = TargetOpcode::G_ADD;
2587 ExtOpcode = TargetOpcode::G_SEXT;
2589 case TargetOpcode::G_SSUBO:
2590 Opcode = TargetOpcode::G_SUB;
2591 ExtOpcode = TargetOpcode::G_SEXT;
2593 case TargetOpcode::G_UADDO:
2594 Opcode = TargetOpcode::G_ADD;
2595 ExtOpcode = TargetOpcode::G_ZEXT;
2597 case TargetOpcode::G_USUBO:
2598 Opcode = TargetOpcode::G_SUB;
2599 ExtOpcode = TargetOpcode::G_ZEXT;
2601 case TargetOpcode::G_SADDE:
2602 Opcode = TargetOpcode::G_UADDE;
2603 ExtOpcode = TargetOpcode::G_SEXT;
2604 CarryIn =
MI.getOperand(4).getReg();
2606 case TargetOpcode::G_SSUBE:
2607 Opcode = TargetOpcode::G_USUBE;
2608 ExtOpcode = TargetOpcode::G_SEXT;
2609 CarryIn =
MI.getOperand(4).getReg();
2611 case TargetOpcode::G_UADDE:
2612 Opcode = TargetOpcode::G_UADDE;
2613 ExtOpcode = TargetOpcode::G_ZEXT;
2614 CarryIn =
MI.getOperand(4).getReg();
2616 case TargetOpcode::G_USUBE:
2617 Opcode = TargetOpcode::G_USUBE;
2618 ExtOpcode = TargetOpcode::G_ZEXT;
2619 CarryIn =
MI.getOperand(4).getReg();
2635 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2636 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2640 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2642 .buildInstr(Opcode, {WideTy, CarryOutTy},
2643 {LHSExt, RHSExt, *CarryIn})
2646 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2648 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2649 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2650 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2655 MI.eraseFromParent();
2660LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2662 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2663 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2664 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2665 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2666 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2679 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2686 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2690 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2691 {ShiftL, ShiftR},
MI.getFlags());
2696 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2699 MI.eraseFromParent();
2704LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2713 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2715 LLT SrcTy = MRI.getType(
LHS);
2716 LLT OverflowTy = MRI.getType(OriginalOverflow);
2723 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2724 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2725 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2732 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2734 MachineInstrBuilder Mulo;
2735 if (WideMulCanOverflow)
2736 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2737 {LeftOperand, RightOperand});
2739 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2744 MachineInstrBuilder ExtResult;
2751 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2755 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2758 if (WideMulCanOverflow) {
2766 MI.eraseFromParent();
2772 unsigned Opcode =
MI.getOpcode();
2776 case TargetOpcode::G_ATOMICRMW_XCHG:
2777 case TargetOpcode::G_ATOMICRMW_ADD:
2778 case TargetOpcode::G_ATOMICRMW_SUB:
2779 case TargetOpcode::G_ATOMICRMW_AND:
2780 case TargetOpcode::G_ATOMICRMW_OR:
2781 case TargetOpcode::G_ATOMICRMW_XOR:
2782 case TargetOpcode::G_ATOMICRMW_MIN:
2783 case TargetOpcode::G_ATOMICRMW_MAX:
2784 case TargetOpcode::G_ATOMICRMW_UMIN:
2785 case TargetOpcode::G_ATOMICRMW_UMAX:
2786 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2792 case TargetOpcode::G_ATOMIC_CMPXCHG:
2793 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2800 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2810 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2815 case TargetOpcode::G_EXTRACT:
2816 return widenScalarExtract(
MI, TypeIdx, WideTy);
2817 case TargetOpcode::G_INSERT:
2818 return widenScalarInsert(
MI, TypeIdx, WideTy);
2819 case TargetOpcode::G_MERGE_VALUES:
2820 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2821 case TargetOpcode::G_UNMERGE_VALUES:
2822 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2823 case TargetOpcode::G_SADDO:
2824 case TargetOpcode::G_SSUBO:
2825 case TargetOpcode::G_UADDO:
2826 case TargetOpcode::G_USUBO:
2827 case TargetOpcode::G_SADDE:
2828 case TargetOpcode::G_SSUBE:
2829 case TargetOpcode::G_UADDE:
2830 case TargetOpcode::G_USUBE:
2831 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2832 case TargetOpcode::G_UMULO:
2833 case TargetOpcode::G_SMULO:
2834 return widenScalarMulo(
MI, TypeIdx, WideTy);
2835 case TargetOpcode::G_SADDSAT:
2836 case TargetOpcode::G_SSUBSAT:
2837 case TargetOpcode::G_SSHLSAT:
2838 case TargetOpcode::G_UADDSAT:
2839 case TargetOpcode::G_USUBSAT:
2840 case TargetOpcode::G_USHLSAT:
2841 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2842 case TargetOpcode::G_CTTZ:
2843 case TargetOpcode::G_CTTZ_ZERO_POISON:
2844 case TargetOpcode::G_CTLZ:
2845 case TargetOpcode::G_CTLZ_ZERO_POISON:
2846 case TargetOpcode::G_CTLS:
2847 case TargetOpcode::G_CTPOP: {
2860 case TargetOpcode::G_CTTZ:
2861 case TargetOpcode::G_CTTZ_ZERO_POISON:
2862 case TargetOpcode::G_CTLZ_ZERO_POISON:
2863 ExtOpc = TargetOpcode::G_ANYEXT;
2865 case TargetOpcode::G_CTLS:
2866 ExtOpc = TargetOpcode::G_SEXT;
2869 ExtOpc = TargetOpcode::G_ZEXT;
2872 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2873 LLT CurTy = MRI.getType(SrcReg);
2874 unsigned NewOpc = Opcode;
2875 if (NewOpc == TargetOpcode::G_CTTZ) {
2882 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2884 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2890 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2900 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2902 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2907 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2908 Opcode == TargetOpcode::G_CTLZ
2913 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2914 MI.eraseFromParent();
2917 case TargetOpcode::G_BSWAP: {
2921 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2922 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2923 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2926 MI.getOperand(0).setReg(DstExt);
2930 LLT Ty = MRI.getType(DstReg);
2932 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2933 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2939 case TargetOpcode::G_BITREVERSE: {
2943 LLT Ty = MRI.getType(DstReg);
2946 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2948 MI.getOperand(0).setReg(DstExt);
2951 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2952 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2957 case TargetOpcode::G_FREEZE:
2958 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2965 case TargetOpcode::G_ABS:
2972 case TargetOpcode::G_ADD:
2973 case TargetOpcode::G_AND:
2974 case TargetOpcode::G_MUL:
2975 case TargetOpcode::G_OR:
2976 case TargetOpcode::G_XOR:
2977 case TargetOpcode::G_SUB:
2978 case TargetOpcode::G_SHUFFLE_VECTOR:
2989 case TargetOpcode::G_SBFX:
2990 case TargetOpcode::G_UBFX:
3004 case TargetOpcode::G_SHL:
3020 case TargetOpcode::G_ROTR:
3021 case TargetOpcode::G_ROTL:
3030 case TargetOpcode::G_SDIV:
3031 case TargetOpcode::G_SREM:
3032 case TargetOpcode::G_SMIN:
3033 case TargetOpcode::G_SMAX:
3034 case TargetOpcode::G_ABDS:
3042 case TargetOpcode::G_SDIVREM:
3052 case TargetOpcode::G_ASHR:
3053 case TargetOpcode::G_LSHR:
3057 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3058 : TargetOpcode::G_ZEXT;
3071 case TargetOpcode::G_UDIV:
3072 case TargetOpcode::G_UREM:
3073 case TargetOpcode::G_ABDU:
3080 case TargetOpcode::G_UDIVREM:
3089 case TargetOpcode::G_UMIN:
3090 case TargetOpcode::G_UMAX: {
3091 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3093 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3097 ? TargetOpcode::G_SEXT
3098 : TargetOpcode::G_ZEXT;
3108 case TargetOpcode::G_SELECT:
3118 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3125 case TargetOpcode::G_FPEXT:
3133 case TargetOpcode::G_FPTOSI:
3134 case TargetOpcode::G_FPTOUI:
3135 case TargetOpcode::G_INTRINSIC_LRINT:
3136 case TargetOpcode::G_INTRINSIC_LLRINT:
3137 case TargetOpcode::G_IS_FPCLASS:
3147 case TargetOpcode::G_SITOFP:
3157 case TargetOpcode::G_UITOFP:
3167 case TargetOpcode::G_FPTOSI_SAT:
3168 case TargetOpcode::G_FPTOUI_SAT:
3173 LLT Ty = MRI.getType(OldDst);
3174 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3176 MI.getOperand(0).setReg(ExtReg);
3177 uint64_t ShortBits = Ty.getScalarSizeInBits();
3180 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3191 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3192 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3200 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3208 case TargetOpcode::G_LOAD:
3209 case TargetOpcode::G_SEXTLOAD:
3210 case TargetOpcode::G_ZEXTLOAD:
3211 case TargetOpcode::G_FPEXTLOAD:
3217 case TargetOpcode::G_STORE: {
3221 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3222 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3223 if (!Ty.isScalar()) {
3231 MI.setMemRefs(MF, {NewMMO});
3238 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3239 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3245 case TargetOpcode::G_FPTRUNCSTORE:
3252 case TargetOpcode::G_CONSTANT: {
3255 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3256 MRI.getType(
MI.getOperand(0).getReg()));
3257 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3258 ExtOpc == TargetOpcode::G_ANYEXT) &&
3261 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3265 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3271 case TargetOpcode::G_FCONSTANT: {
3277 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3279 MI.eraseFromParent();
3282 case TargetOpcode::G_IMPLICIT_DEF: {
3288 case TargetOpcode::G_BRCOND:
3294 case TargetOpcode::G_FCMP:
3305 case TargetOpcode::G_ICMP:
3310 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3314 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3315 unsigned ExtOpcode =
3319 ? TargetOpcode::G_SEXT
3320 : TargetOpcode::G_ZEXT;
3327 case TargetOpcode::G_PTR_ADD:
3328 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3334 case TargetOpcode::G_PHI: {
3335 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3338 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3350 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3353 LLT VecTy = MRI.getType(VecReg);
3357 TargetOpcode::G_ANYEXT);
3371 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3387 LLT VecTy = MRI.getType(VecReg);
3406 case TargetOpcode::G_FADD:
3407 case TargetOpcode::G_FMUL:
3408 case TargetOpcode::G_FSUB:
3409 case TargetOpcode::G_FMA:
3410 case TargetOpcode::G_FMAD:
3411 case TargetOpcode::G_FNEG:
3412 case TargetOpcode::G_FABS:
3413 case TargetOpcode::G_FCANONICALIZE:
3414 case TargetOpcode::G_FMINNUM:
3415 case TargetOpcode::G_FMAXNUM:
3416 case TargetOpcode::G_FMINNUM_IEEE:
3417 case TargetOpcode::G_FMAXNUM_IEEE:
3418 case TargetOpcode::G_FMINIMUM:
3419 case TargetOpcode::G_FMAXIMUM:
3420 case TargetOpcode::G_FMINIMUMNUM:
3421 case TargetOpcode::G_FMAXIMUMNUM:
3422 case TargetOpcode::G_FDIV:
3423 case TargetOpcode::G_FREM:
3424 case TargetOpcode::G_FCEIL:
3425 case TargetOpcode::G_FFLOOR:
3426 case TargetOpcode::G_FCOS:
3427 case TargetOpcode::G_FSIN:
3428 case TargetOpcode::G_FTAN:
3429 case TargetOpcode::G_FACOS:
3430 case TargetOpcode::G_FASIN:
3431 case TargetOpcode::G_FATAN:
3432 case TargetOpcode::G_FATAN2:
3433 case TargetOpcode::G_FCOSH:
3434 case TargetOpcode::G_FSINH:
3435 case TargetOpcode::G_FTANH:
3436 case TargetOpcode::G_FLOG10:
3437 case TargetOpcode::G_FLOG:
3438 case TargetOpcode::G_FLOG2:
3439 case TargetOpcode::G_FRINT:
3440 case TargetOpcode::G_FNEARBYINT:
3441 case TargetOpcode::G_FSQRT:
3442 case TargetOpcode::G_FEXP:
3443 case TargetOpcode::G_FEXP2:
3444 case TargetOpcode::G_FEXP10:
3445 case TargetOpcode::G_FPOW:
3446 case TargetOpcode::G_INTRINSIC_TRUNC:
3447 case TargetOpcode::G_INTRINSIC_ROUND:
3448 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3452 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3458 case TargetOpcode::G_FMODF: {
3468 case TargetOpcode::G_FPOWI:
3469 case TargetOpcode::G_FLDEXP:
3470 case TargetOpcode::G_STRICT_FLDEXP: {
3472 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3493 case TargetOpcode::G_FFREXP: {
3506 case TargetOpcode::G_LROUND:
3507 case TargetOpcode::G_LLROUND:
3518 case TargetOpcode::G_INTTOPTR:
3526 case TargetOpcode::G_PTRTOINT:
3534 case TargetOpcode::G_BUILD_VECTOR: {
3538 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3544 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3552 case TargetOpcode::G_SEXT_INREG:
3561 case TargetOpcode::G_PTRMASK: {
3569 case TargetOpcode::G_VECREDUCE_ADD: {
3578 case TargetOpcode::G_VECREDUCE_FADD:
3579 case TargetOpcode::G_VECREDUCE_FMUL:
3580 case TargetOpcode::G_VECREDUCE_FMIN:
3581 case TargetOpcode::G_VECREDUCE_FMAX:
3582 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3583 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3588 LLT VecTy = MRI.getType(VecReg);
3595 case TargetOpcode::G_VSCALE: {
3602 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3607 case TargetOpcode::G_SPLAT_VECTOR: {
3616 case TargetOpcode::G_INSERT_SUBVECTOR: {
3624 LLT SubVecTy = MRI.getType(SubVec);
3628 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3629 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3630 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3634 auto SplatZero =
MIRBuilder.buildSplatVector(
3639 MI.eraseFromParent();
3643 case TargetOpcode::G_BITCAST:
3655 if (MRI.getType(Dst) == MRI.getType(Src)) {
3656 Observer.changingAllUsesOfReg(MRI, Dst);
3657 MRI.replaceRegWith(Dst, Src);
3658 Observer.finishedChangingAllUsesOfReg();
3659 MI.eraseFromParent();
3668 auto Unmerge =
B.buildUnmerge(Ty, Src);
3669 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3678 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3692 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3701 MI.eraseFromParent();
3712 MI.eraseFromParent();
3719 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3720 if (SrcTy.isVector()) {
3724 if (DstTy.isVector()) {
3725 int NumDstElt = DstTy.getNumElements();
3726 int NumSrcElt = SrcTy.getNumElements();
3729 LLT DstCastTy = DstEltTy;
3730 LLT SrcPartTy = SrcEltTy;
3734 if (NumSrcElt < NumDstElt) {
3745 SrcPartTy = SrcEltTy;
3746 }
else if (NumSrcElt > NumDstElt) {
3758 DstCastTy = DstEltTy;
3763 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3767 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3768 MI.eraseFromParent();
3772 if (DstTy.isVector()) {
3775 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3776 MI.eraseFromParent();
3792 unsigned NewEltSize,
3793 unsigned OldEltSize) {
3794 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3795 LLT IdxTy =
B.getMRI()->getType(Idx);
3798 auto OffsetMask =
B.buildConstant(
3800 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3801 return B.buildShl(IdxTy, OffsetIdx,
3802 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3817 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3821 unsigned OldNumElts = SrcVecTy.getNumElements();
3828 if (NewNumElts > OldNumElts) {
3839 if (NewNumElts % OldNumElts != 0)
3843 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3847 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3850 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3852 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3853 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3854 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3855 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3856 NewOps[
I] = Elt.getReg(0);
3859 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3861 MI.eraseFromParent();
3865 if (NewNumElts < OldNumElts) {
3866 if (NewEltSize % OldEltSize != 0)
3888 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3889 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3892 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3896 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3897 ScaledIdx).getReg(0);
3905 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3907 MI.eraseFromParent();
3921 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3922 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3923 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3924 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3927 auto EltMask =
B.buildConstant(
3931 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3932 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3935 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3939 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3953 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3954 MI.getFirst4RegLLTs();
3966 if (NewNumElts < OldNumElts) {
3967 if (NewEltSize % OldEltSize != 0)
3976 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3977 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3980 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3984 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3985 ScaledIdx).getReg(0);
3995 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3996 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4000 MI.eraseFromParent();
4030 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4034 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4035 return UnableToLegalize;
4040 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4042 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4051 MI.eraseFromParent();
4069 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4070 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4080 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4081 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4083 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4084 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4086 MI.eraseFromParent();
4116 LLT DstTy = MRI.getType(Dst);
4117 LLT SrcTy = MRI.getType(Src);
4123 if (DstTy == CastTy)
4131 if (CastEltSize < DstEltSize)
4134 auto AdjustAmt = CastEltSize / DstEltSize;
4135 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4136 SrcTyMinElts % AdjustAmt != 0)
4141 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4142 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4145 ES->eraseFromParent();
4180 LLT DstTy = MRI.getType(Dst);
4181 LLT BigVecTy = MRI.getType(BigVec);
4182 LLT SubVecTy = MRI.getType(SubVec);
4184 if (DstTy == CastTy)
4199 if (CastEltSize < DstEltSize)
4202 auto AdjustAmt = CastEltSize / DstEltSize;
4203 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4204 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4210 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4211 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4213 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4216 ES->eraseFromParent();
4224 LLT DstTy = MRI.getType(DstReg);
4234 if (MemSizeInBits != MemStoreSizeInBits) {
4251 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4255 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4256 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4258 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4261 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4263 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4266 if (DstTy != LoadTy)
4274 if (
MIRBuilder.getDataLayout().isBigEndian())
4292 uint64_t LargeSplitSize, SmallSplitSize;
4297 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4304 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4307 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4318 if (Alignment.
value() * 8 > MemSizeInBits &&
4323 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4340 LLT PtrTy = MRI.getType(PtrReg);
4353 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4356 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4357 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4358 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4360 SmallPtr, *SmallMMO);
4362 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4363 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4365 if (AnyExtTy == DstTy)
4366 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4368 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4372 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4392 LLT SrcTy = MRI.getType(SrcReg);
4400 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4406 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4408 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4412 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4416 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4431 uint64_t LargeSplitSize, SmallSplitSize;
4438 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4441 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4450 if (SrcTy.isPointer()) {
4455 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4458 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4459 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4462 LLT PtrTy = MRI.getType(PtrReg);
4464 LargeSplitSize / 8);
4465 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4471 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4472 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4481 LLT SrcTy = MRI.getType(SrcReg);
4487 assert(SrcTy.isVector() &&
"Expect a vector store type");
4494 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4498 auto Elt =
MIRBuilder.buildExtractVectorElement(
4499 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4500 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4501 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4507 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4508 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4512 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4523 switch (
MI.getOpcode()) {
4524 case TargetOpcode::G_LOAD: {
4542 case TargetOpcode::G_STORE: {
4558 case TargetOpcode::G_SELECT: {
4562 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4564 dbgs() <<
"bitcast action not implemented for vector select\n");
4575 case TargetOpcode::G_AND:
4576 case TargetOpcode::G_OR:
4577 case TargetOpcode::G_XOR: {
4585 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4587 case TargetOpcode::G_INSERT_VECTOR_ELT:
4589 case TargetOpcode::G_CONCAT_VECTORS:
4591 case TargetOpcode::G_SHUFFLE_VECTOR:
4593 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4595 case TargetOpcode::G_INSERT_SUBVECTOR:
4603void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4612 switch(
MI.getOpcode()) {
4615 case TargetOpcode::G_FCONSTANT:
4617 case TargetOpcode::G_BITCAST:
4619 case TargetOpcode::G_SREM:
4620 case TargetOpcode::G_UREM: {
4621 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4623 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4624 {MI.getOperand(1), MI.getOperand(2)});
4626 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4628 MI.eraseFromParent();
4631 case TargetOpcode::G_SADDO:
4632 case TargetOpcode::G_SSUBO:
4634 case TargetOpcode::G_SADDE:
4636 case TargetOpcode::G_SSUBE:
4638 case TargetOpcode::G_UMULH:
4639 case TargetOpcode::G_SMULH:
4641 case TargetOpcode::G_SMULO:
4642 case TargetOpcode::G_UMULO: {
4645 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4646 LLT Ty = MRI.getType(Res);
4648 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4649 ? TargetOpcode::G_SMULH
4650 : TargetOpcode::G_UMULH;
4654 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4655 MI.removeOperand(1);
4658 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4666 if (Opcode == TargetOpcode::G_SMULH) {
4667 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4668 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4675 case TargetOpcode::G_FNEG: {
4676 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4679 Register CastedSubByReg = SubByReg;
4681 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4682 !SubByRegTy.getScalarType().isInteger()) {
4683 auto BitcastDst = SubByRegTy.changeElementType(
4685 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4691 if (ResTy != TyInt) {
4693 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4696 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4698 MI.eraseFromParent();
4701 case TargetOpcode::G_FSUB:
4702 case TargetOpcode::G_STRICT_FSUB: {
4703 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4704 LLT Ty = MRI.getType(Res);
4709 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4710 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4714 MI.eraseFromParent();
4717 case TargetOpcode::G_FMAD:
4719 case TargetOpcode::G_FFLOOR:
4721 case TargetOpcode::G_LROUND:
4722 case TargetOpcode::G_LLROUND: {
4725 LLT SrcTy = MRI.getType(SrcReg);
4726 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4729 MI.eraseFromParent();
4732 case TargetOpcode::G_INTRINSIC_ROUND:
4734 case TargetOpcode::G_FRINT: {
4737 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4740 case TargetOpcode::G_INTRINSIC_LRINT:
4741 case TargetOpcode::G_INTRINSIC_LLRINT: {
4744 LLT SrcTy = MRI.getType(SrcReg);
4746 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4748 MI.eraseFromParent();
4751 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4752 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4753 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4754 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4755 **
MI.memoperands_begin());
4757 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4758 MI.eraseFromParent();
4761 case TargetOpcode::G_LOAD:
4762 case TargetOpcode::G_SEXTLOAD:
4763 case TargetOpcode::G_ZEXTLOAD:
4765 case TargetOpcode::G_STORE:
4767 case TargetOpcode::G_CTLZ_ZERO_POISON:
4768 case TargetOpcode::G_CTTZ_ZERO_POISON:
4769 case TargetOpcode::G_CTLZ:
4770 case TargetOpcode::G_CTTZ:
4771 case TargetOpcode::G_CTPOP:
4772 case TargetOpcode::G_CTLS:
4775 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4777 Register NewRes = MRI.cloneVirtualRegister(Res);
4784 MI.eraseFromParent();
4788 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4789 const LLT CondTy = MRI.getType(CarryOut);
4790 const LLT Ty = MRI.getType(Res);
4792 Register NewRes = MRI.cloneVirtualRegister(Res);
4795 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4801 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4802 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4809 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4814 MI.eraseFromParent();
4818 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4823 MI.eraseFromParent();
4827 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4828 const LLT CondTy = MRI.getType(BorrowOut);
4829 const LLT Ty = MRI.getType(Res);
4832 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4838 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4839 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4846 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4847 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4849 MI.eraseFromParent();
4889 case G_MERGE_VALUES:
4891 case G_UNMERGE_VALUES:
4893 case TargetOpcode::G_SEXT_INREG: {
4894 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4895 int64_t SizeInBits =
MI.getOperand(2).getImm();
4897 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4898 LLT DstTy = MRI.getType(DstReg);
4899 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4902 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4903 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4904 MI.eraseFromParent();
4907 case G_EXTRACT_VECTOR_ELT:
4908 case G_INSERT_VECTOR_ELT:
4910 case G_SHUFFLE_VECTOR:
4912 case G_VECTOR_COMPRESS:
4914 case G_DYN_STACKALLOC:
4916 case G_INSERT_SUBVECTOR: {
4917 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4918 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4923 Register Subvector =
MI.getOperand(2).getReg();
4924 auto InsertionPointImm =
MI.getOperand(3).getImm();
4927 LLT SubvectorTy = MRI.getType(Subvector);
4931 bool InsertInLowHalf = InsertionPointImm == 0;
4932 auto Extract =
MIRBuilder.buildExtractSubvector(
4936 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4937 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4939 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4940 {LowHalf, HighHalf});
4941 MI.eraseFromParent();
4947 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4948 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4954 if (i >= InsertionPointImm &&
4956 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
4964 MI.eraseFromParent();
4970 case G_STACKRESTORE:
4980 case G_READ_REGISTER:
4981 case G_WRITE_REGISTER:
4988 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4989 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4995 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5000 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5011 bool IsSigned =
MI.getOpcode() == G_ABDS;
5012 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5013 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5014 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5037 case G_MEMCPY_INLINE:
5038 case G_MEMSET_INLINE:
5050 case G_ATOMICRMW_SUB: {
5051 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5052 const LLT ValTy = MRI.getType(Val);
5056 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5057 MI.eraseFromParent();
5083 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5087 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5093 Align StackTypeAlign =
5100 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5101 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5106 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5118 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
5121 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5132 "Converting bits to bytes lost precision");
5138 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5139 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5141 if (IdxTy != MRI.getType(Index))
5142 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5147 LLT PtrTy = MRI.getType(VecPtr);
5148 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5156 std::initializer_list<unsigned> NonVecOpIndices) {
5157 if (
MI.getNumMemOperands() != 0)
5174 if (!Ty.isVector()) {
5180 if (Ty.getNumElements() != NumElts)
5195 assert(Ty.isVector() &&
"Expected vector type");
5197 int NumParts, NumLeftover;
5198 std::tie(NumParts, NumLeftover) =
5201 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5202 for (
int i = 0; i < NumParts; ++i) {
5207 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5216 for (
unsigned i = 0; i <
N; ++i) {
5218 Ops.push_back(
Op.getReg());
5219 else if (
Op.isImm())
5220 Ops.push_back(
Op.getImm());
5221 else if (
Op.isPredicate())
5243 std::initializer_list<unsigned> NonVecOpIndices) {
5245 "Non-compatible opcode or not specified non-vector operands");
5246 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5248 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5249 unsigned NumDefs =
MI.getNumDefs();
5257 for (
unsigned i = 0; i < NumDefs; ++i) {
5258 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5266 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5267 ++UseIdx, ++UseNo) {
5270 MI.getOperand(UseIdx));
5279 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5283 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5285 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5286 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5289 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5290 Uses.push_back(InputOpsPieces[InputNo][i]);
5293 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5294 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5299 for (
unsigned i = 0; i < NumDefs; ++i)
5300 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5302 for (
unsigned i = 0; i < NumDefs; ++i)
5303 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5306 MI.eraseFromParent();
5313 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5315 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5316 unsigned NumDefs =
MI.getNumDefs();
5320 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5325 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5326 UseIdx += 2, ++UseNo) {
5334 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5336 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5337 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5339 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5342 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5343 Phi.addUse(InputOpsPieces[j][i]);
5344 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5354 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5356 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5359 MI.eraseFromParent();
5367 const int NumDst =
MI.getNumOperands() - 1;
5368 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5369 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5370 LLT SrcTy = MRI.getType(SrcReg);
5372 if (TypeIdx != 1 || NarrowTy == DstTy)
5379 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5382 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5396 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5397 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5398 const int PartsPerUnmerge = NumDst / NumUnmerge;
5400 for (
int I = 0;
I != NumUnmerge; ++
I) {
5401 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5403 for (
int J = 0; J != PartsPerUnmerge; ++J)
5404 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5405 MIB.addUse(Unmerge.getReg(
I));
5408 MI.eraseFromParent();
5415 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5419 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5421 if (NarrowTy == SrcTy)
5429 assert(SrcTy.isVector() &&
"Expected vector types");
5431 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5445 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5446 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5447 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5453 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5454 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5455 ++i,
Offset += NumNarrowTyElts) {
5458 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5461 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5462 MI.eraseFromParent();
5466 assert(TypeIdx == 0 &&
"Bad type index");
5467 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5482 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5483 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5485 for (
unsigned i = 0; i < NumParts; ++i) {
5487 for (
unsigned j = 0; j < NumElts; ++j)
5488 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5490 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5493 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5494 MI.eraseFromParent();
5502 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5504 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5506 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5508 InsertVal =
MI.getOperand(2).getReg();
5510 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5511 LLT VecTy = MRI.getType(SrcVec);
5517 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5521 MI.eraseFromParent();
5530 SplitPieces[IdxVal] = InsertVal;
5531 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5533 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5537 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5540 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5541 TargetOpcode::G_ANYEXT);
5545 LLT IdxTy = MRI.getType(Idx);
5546 int64_t PartIdx = IdxVal / NewNumElts;
5548 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5551 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5554 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5555 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5556 VecParts[PartIdx] = InsertPart.getReg(0);
5560 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5562 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5566 MI.eraseFromParent();
5586 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5598 LLT ValTy = MRI.getType(ValReg);
5607 int NumLeftover = -1;
5613 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5615 NumParts = NarrowRegs.
size();
5616 NumLeftover = NarrowLeftoverRegs.
size();
5623 LLT PtrTy = MRI.getType(AddrReg);
5633 auto MMO = LdStMI.
getMMO();
5635 unsigned NumParts,
unsigned Offset) ->
unsigned {
5638 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5640 unsigned ByteOffset =
Offset / 8;
5643 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5650 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5651 ValRegs.push_back(Dst);
5652 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5654 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5663 unsigned HandledOffset =
5664 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5668 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5671 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5672 LeftoverTy, NarrowLeftoverRegs);
5686 switch (
MI.getOpcode()) {
5687 case G_IMPLICIT_DEF:
5703 case G_FCANONICALIZE:
5720 case G_INTRINSIC_LRINT:
5721 case G_INTRINSIC_LLRINT:
5722 case G_INTRINSIC_ROUND:
5723 case G_INTRINSIC_ROUNDEVEN:
5726 case G_INTRINSIC_TRUNC:
5754 case G_FMINNUM_IEEE:
5755 case G_FMAXNUM_IEEE:
5777 case G_CTLZ_ZERO_POISON:
5779 case G_CTTZ_ZERO_POISON:
5796 case G_ADDRSPACE_CAST:
5809 case G_STRICT_FLDEXP:
5811 case G_TRUNC_SSAT_S:
5812 case G_TRUNC_SSAT_U:
5813 case G_TRUNC_USAT_U:
5821 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5826 case G_UNMERGE_VALUES:
5828 case G_BUILD_VECTOR:
5829 assert(TypeIdx == 0 &&
"not a vector type index");
5831 case G_CONCAT_VECTORS:
5835 case G_EXTRACT_VECTOR_ELT:
5836 case G_INSERT_VECTOR_ELT:
5845 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5846 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5848 case G_SHUFFLE_VECTOR:
5854 case G_INTRINSIC_FPTRUNC_ROUND:
5864 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5865 "Not a bitcast operation");
5870 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5872 unsigned NewElemCount =
5875 if (NewElemCount == 1) {
5878 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5885 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5894 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5895 MI.eraseFromParent();
5901 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5905 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5906 MI.getFirst3RegLLTs();
5909 if (DstTy != Src1Ty)
5911 if (DstTy != Src2Ty)
5926 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5942 unsigned InputUsed[2] = {-1U, -1U};
5943 unsigned FirstMaskIdx =
High * NewElts;
5944 bool UseBuildVector =
false;
5945 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5947 int Idx = Mask[FirstMaskIdx + MaskOffset];
5952 if (
Input >= std::size(Inputs)) {
5959 Idx -=
Input * NewElts;
5963 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5964 if (InputUsed[OpNo] ==
Input) {
5967 }
else if (InputUsed[OpNo] == -1U) {
5969 InputUsed[OpNo] =
Input;
5974 if (OpNo >= std::size(InputUsed)) {
5977 UseBuildVector =
true;
5982 Ops.push_back(Idx + OpNo * NewElts);
5985 if (UseBuildVector) {
5990 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5992 int Idx = Mask[FirstMaskIdx + MaskOffset];
5997 if (
Input >= std::size(Inputs)) {
6004 Idx -=
Input * NewElts;
6008 .buildExtractVectorElement(
6009 EltTy, Inputs[
Input],
6015 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6016 }
else if (InputUsed[0] == -1U) {
6018 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6019 }
else if (NewElts == 1) {
6020 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6022 Register Op0 = Inputs[InputUsed[0]];
6026 : Inputs[InputUsed[1]];
6028 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6035 MI.eraseFromParent();
6048 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6054 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6057 const unsigned NumParts =
6059 : SrcTy.getNumElements();
6063 if (DstTy != NarrowTy)
6069 unsigned NumPartsLeft = NumParts;
6070 while (NumPartsLeft > 1) {
6071 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6074 .buildInstr(ScalarOpc, {NarrowTy},
6075 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
6078 SplitSrcs = PartialResults;
6079 PartialResults.
clear();
6080 NumPartsLeft = SplitSrcs.
size();
6084 MI.eraseFromParent();
6089 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6090 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
6093 MI.eraseFromParent();
6097 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6099 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
6107 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6110 Register Acc = PartialReductions[0];
6111 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6112 if (Part == NumParts - 1) {
6114 {Acc, PartialReductions[Part]});
6117 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
6121 MI.eraseFromParent();
6127 unsigned int TypeIdx,
6129 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6130 MI.getFirst3RegLLTs();
6131 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6135 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6136 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6137 "Unexpected vecreduce opcode");
6138 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6139 ? TargetOpcode::G_FADD
6140 : TargetOpcode::G_FMUL;
6143 unsigned NumParts = SrcTy.getNumElements();
6146 for (
unsigned i = 0; i < NumParts; i++)
6147 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
6151 MI.eraseFromParent();
6158 unsigned ScalarOpc) {
6166 while (SplitSrcs.
size() > 1) {
6168 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6176 SplitSrcs = std::move(PartialRdxs);
6180 MI.getOperand(1).setReg(SplitSrcs[0]);
6187 const LLT HalfTy,
const LLT AmtTy) {
6189 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6190 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6194 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6195 MI.eraseFromParent();
6201 unsigned VTBits = 2 * NVTBits;
6204 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6205 if (Amt.
ugt(VTBits)) {
6207 }
else if (Amt.
ugt(NVTBits)) {
6210 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6211 }
else if (Amt == NVTBits) {
6219 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6222 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6223 if (Amt.
ugt(VTBits)) {
6225 }
else if (Amt.
ugt(NVTBits)) {
6227 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6229 }
else if (Amt == NVTBits) {
6233 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6235 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6237 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6243 if (Amt.
ugt(VTBits)) {
6245 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6246 }
else if (Amt.
ugt(NVTBits)) {
6248 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6250 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6251 }
else if (Amt == NVTBits) {
6254 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6256 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6258 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6260 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6267 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6268 MI.eraseFromParent();
6284 LLT DstTy = MRI.getType(DstReg);
6289 LLT ShiftAmtTy = MRI.getType(Amt);
6291 if (DstEltSize % 2 != 0)
6307 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6318 const unsigned NewBitSize = DstEltSize / 2;
6330 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6332 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6333 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6336 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6337 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6339 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6344 switch (
MI.getOpcode()) {
6345 case TargetOpcode::G_SHL: {
6347 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6349 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6350 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6351 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6354 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6355 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6357 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6359 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6361 ResultRegs[0] =
Lo.getReg(0);
6362 ResultRegs[1] =
Hi.getReg(0);
6365 case TargetOpcode::G_LSHR:
6366 case TargetOpcode::G_ASHR: {
6368 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6370 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6371 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6372 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6376 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6379 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6380 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6382 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6386 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6388 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6390 ResultRegs[0] =
Lo.getReg(0);
6391 ResultRegs[1] =
Hi.getReg(0);
6398 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6399 MI.eraseFromParent();
6408 LLT TargetTy,
LLT ShiftAmtTy) {
6411 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6413 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6414 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6415 const bool NeedsInterWordShift = ShiftBits != 0;
6418 case TargetOpcode::G_SHL: {
6421 if (PartIdx < ShiftWords)
6424 unsigned SrcIdx = PartIdx - ShiftWords;
6425 if (!NeedsInterWordShift)
6426 return SrcParts[SrcIdx];
6431 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6435 return Hi.getReg(0);
6438 case TargetOpcode::G_LSHR: {
6439 unsigned SrcIdx = PartIdx + ShiftWords;
6440 if (SrcIdx >= NumParts)
6442 if (!NeedsInterWordShift)
6443 return SrcParts[SrcIdx];
6447 if (SrcIdx + 1 < NumParts) {
6448 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6452 return Lo.getReg(0);
6455 case TargetOpcode::G_ASHR: {
6457 unsigned SrcIdx = PartIdx + ShiftWords;
6458 if (SrcIdx >= NumParts)
6460 if (!NeedsInterWordShift)
6461 return SrcParts[SrcIdx];
6466 (SrcIdx == NumParts - 1)
6470 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6492 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6493 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6498 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6507 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6508 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6510 auto IsZeroBitShift =
6518 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6519 : TargetOpcode::G_SHL;
6522 auto TargetBitsConst =
6524 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6529 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6534 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6536 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6540 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6553 LLT DstTy = MRI.getType(DstReg);
6557 const unsigned NumParts = DstBits / TargetBits;
6559 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6569 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6570 MI.eraseFromParent();
6575 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6576 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6582 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6586 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6589 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6590 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6594 for (
unsigned I = 0;
I < NumParts; ++
I)
6596 Params, TargetTy, ShiftAmtTy);
6598 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6599 MI.eraseFromParent();
6608 LLT DstTy = MRI.getType(DstReg);
6609 LLT ShiftAmtTy = MRI.getType(AmtReg);
6613 const unsigned NumParts = DstBits / TargetBits;
6615 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6632 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6644 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6645 auto TargetBitsLog2Const =
6646 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6647 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6650 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6652 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6660 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6661 auto TargetBitsMinusOneConst =
6662 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6664 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6665 TargetBitsMinusOneConst)
6668 FillValue = ZeroReg;
6676 for (
unsigned I = 0;
I < NumParts; ++
I) {
6678 Register InBoundsResult = FillValue;
6688 for (
unsigned K = 0; K < NumParts; ++K) {
6689 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6691 WordShift, WordShiftKConst);
6703 switch (
MI.getOpcode()) {
6704 case TargetOpcode::G_SHL:
6705 MainSrcIdx = (int)
I - (
int)K;
6706 CarrySrcIdx = MainSrcIdx - 1;
6708 case TargetOpcode::G_LSHR:
6709 case TargetOpcode::G_ASHR:
6710 MainSrcIdx = (int)
I + (
int)K;
6711 CarrySrcIdx = MainSrcIdx + 1;
6719 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6720 Register MainOp = SrcParts[MainSrcIdx];
6724 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6725 CarryOp = SrcParts[CarrySrcIdx];
6726 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6727 CarrySrcIdx >= (
int)NumParts)
6728 CarryOp = FillValue;
6734 ResultForK = FillValue;
6740 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6747 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6751 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6752 MI.eraseFromParent();
6759 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6762 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6777 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6782 "getNeutralElementForVecReduce called with invalid opcode!");
6783 case TargetOpcode::G_VECREDUCE_ADD:
6784 case TargetOpcode::G_VECREDUCE_OR:
6785 case TargetOpcode::G_VECREDUCE_XOR:
6786 case TargetOpcode::G_VECREDUCE_UMAX:
6788 case TargetOpcode::G_VECREDUCE_MUL:
6790 case TargetOpcode::G_VECREDUCE_AND:
6791 case TargetOpcode::G_VECREDUCE_UMIN:
6794 case TargetOpcode::G_VECREDUCE_SMAX:
6797 case TargetOpcode::G_VECREDUCE_SMIN:
6800 case TargetOpcode::G_VECREDUCE_FADD:
6802 case TargetOpcode::G_VECREDUCE_FMUL:
6804 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6805 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6806 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6807 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6815 unsigned Opc =
MI.getOpcode();
6817 case TargetOpcode::G_IMPLICIT_DEF:
6818 case TargetOpcode::G_LOAD: {
6826 case TargetOpcode::G_STORE:
6833 case TargetOpcode::G_AND:
6834 case TargetOpcode::G_OR:
6835 case TargetOpcode::G_XOR:
6836 case TargetOpcode::G_ADD:
6837 case TargetOpcode::G_SUB:
6838 case TargetOpcode::G_MUL:
6839 case TargetOpcode::G_FADD:
6840 case TargetOpcode::G_FSUB:
6841 case TargetOpcode::G_FMUL:
6842 case TargetOpcode::G_FDIV:
6843 case TargetOpcode::G_FCOPYSIGN:
6844 case TargetOpcode::G_UADDSAT:
6845 case TargetOpcode::G_USUBSAT:
6846 case TargetOpcode::G_SADDSAT:
6847 case TargetOpcode::G_SSUBSAT:
6848 case TargetOpcode::G_SMIN:
6849 case TargetOpcode::G_SMAX:
6850 case TargetOpcode::G_UMIN:
6851 case TargetOpcode::G_UMAX:
6852 case TargetOpcode::G_FMINNUM:
6853 case TargetOpcode::G_FMAXNUM:
6854 case TargetOpcode::G_FMINNUM_IEEE:
6855 case TargetOpcode::G_FMAXNUM_IEEE:
6856 case TargetOpcode::G_FMINIMUM:
6857 case TargetOpcode::G_FMAXIMUM:
6858 case TargetOpcode::G_FMINIMUMNUM:
6859 case TargetOpcode::G_FMAXIMUMNUM:
6860 case TargetOpcode::G_STRICT_FADD:
6861 case TargetOpcode::G_STRICT_FSUB:
6862 case TargetOpcode::G_STRICT_FMUL: {
6870 case TargetOpcode::G_SHL:
6871 case TargetOpcode::G_ASHR:
6872 case TargetOpcode::G_LSHR: {
6878 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6884 case TargetOpcode::G_FMA:
6885 case TargetOpcode::G_STRICT_FMA:
6886 case TargetOpcode::G_FSHR:
6887 case TargetOpcode::G_FSHL: {
6896 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6897 case TargetOpcode::G_EXTRACT:
6904 case TargetOpcode::G_INSERT:
6905 case TargetOpcode::G_INSERT_VECTOR_ELT:
6906 case TargetOpcode::G_FREEZE:
6907 case TargetOpcode::G_FNEG:
6908 case TargetOpcode::G_FABS:
6909 case TargetOpcode::G_FSQRT:
6910 case TargetOpcode::G_FCEIL:
6911 case TargetOpcode::G_FFLOOR:
6912 case TargetOpcode::G_FNEARBYINT:
6913 case TargetOpcode::G_FRINT:
6914 case TargetOpcode::G_INTRINSIC_ROUND:
6915 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6916 case TargetOpcode::G_INTRINSIC_TRUNC:
6917 case TargetOpcode::G_BITREVERSE:
6918 case TargetOpcode::G_BSWAP:
6919 case TargetOpcode::G_FCANONICALIZE:
6920 case TargetOpcode::G_SEXT_INREG:
6921 case TargetOpcode::G_ABS:
6922 case TargetOpcode::G_CTLZ:
6923 case TargetOpcode::G_CTPOP:
6931 case TargetOpcode::G_SELECT: {
6932 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6934 if (!CondTy.isScalar() ||
6940 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6942 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6947 if (CondTy.isVector())
6957 case TargetOpcode::G_UNMERGE_VALUES:
6959 case TargetOpcode::G_PHI:
6961 case TargetOpcode::G_SHUFFLE_VECTOR:
6963 case TargetOpcode::G_BUILD_VECTOR: {
6965 for (
auto Op :
MI.uses()) {
6973 MIRBuilder.buildDeleteTrailingVectorElements(
6974 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6975 MI.eraseFromParent();
6978 case TargetOpcode::G_SEXT:
6979 case TargetOpcode::G_ZEXT:
6980 case TargetOpcode::G_ANYEXT:
6981 case TargetOpcode::G_TRUNC:
6982 case TargetOpcode::G_FPTRUNC:
6983 case TargetOpcode::G_FPEXT:
6984 case TargetOpcode::G_FPTOSI:
6985 case TargetOpcode::G_FPTOUI:
6986 case TargetOpcode::G_FPTOSI_SAT:
6987 case TargetOpcode::G_FPTOUI_SAT:
6988 case TargetOpcode::G_SITOFP:
6989 case TargetOpcode::G_UITOFP: {
6996 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6999 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7007 case TargetOpcode::G_ICMP:
7008 case TargetOpcode::G_FCMP: {
7016 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7021 case TargetOpcode::G_BITCAST: {
7025 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7026 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7042 case TargetOpcode::G_VECREDUCE_FADD:
7043 case TargetOpcode::G_VECREDUCE_FMUL:
7044 case TargetOpcode::G_VECREDUCE_ADD:
7045 case TargetOpcode::G_VECREDUCE_MUL:
7046 case TargetOpcode::G_VECREDUCE_AND:
7047 case TargetOpcode::G_VECREDUCE_OR:
7048 case TargetOpcode::G_VECREDUCE_XOR:
7049 case TargetOpcode::G_VECREDUCE_SMAX:
7050 case TargetOpcode::G_VECREDUCE_SMIN:
7051 case TargetOpcode::G_VECREDUCE_UMAX:
7052 case TargetOpcode::G_VECREDUCE_UMIN: {
7053 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7055 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7056 auto NeutralElement = getNeutralElementForVecReduce(
7062 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7063 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7064 NeutralElement, Idx);
7068 MO.
setReg(NewVec.getReg(0));
7080 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7082 unsigned MaskNumElts = Mask.size();
7083 unsigned SrcNumElts = SrcTy.getNumElements();
7086 if (MaskNumElts == SrcNumElts)
7089 if (MaskNumElts < SrcNumElts) {
7097 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7098 MI.getOperand(1).getReg(),
7099 MI.getOperand(2).getReg(), NewMask);
7100 MI.eraseFromParent();
7105 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7106 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7115 MOps1[0] =
MI.getOperand(1).getReg();
7116 MOps2[0] =
MI.getOperand(2).getReg();
7118 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7119 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7123 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7125 if (Idx >=
static_cast<int>(SrcNumElts))
7126 Idx += PaddedMaskNumElts - SrcNumElts;
7131 if (MaskNumElts != PaddedMaskNumElts) {
7133 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7136 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7138 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7143 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7146 MI.eraseFromParent();
7152 unsigned int TypeIdx,
LLT MoreTy) {
7153 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7155 unsigned NumElts = DstTy.getNumElements();
7158 if (DstTy.isVector() && Src1Ty.isVector() &&
7159 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7167 if (DstTy != Src1Ty || DstTy != Src2Ty)
7175 for (
unsigned I = 0;
I != NumElts; ++
I) {
7177 if (Idx <
static_cast<int>(NumElts))
7180 NewMask[
I] = Idx - NumElts + WidenNumElts;
7184 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7185 MI.getOperand(1).getReg(),
7186 MI.getOperand(2).getReg(), NewMask);
7187 MI.eraseFromParent();
7196 unsigned SrcParts = Src1Regs.
size();
7197 unsigned DstParts = DstRegs.
size();
7199 unsigned DstIdx = 0;
7201 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7202 DstRegs[DstIdx] = FactorSum;
7207 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7209 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7210 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7212 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7218 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7219 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7220 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7221 unsigned i = RevI - 1;
7223 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7233 if (DstIdx != DstParts - 1) {
7234 MachineInstrBuilder Uaddo =
7235 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7236 FactorSum = Uaddo.
getReg(0);
7237 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7238 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7239 MachineInstrBuilder Uaddo =
7240 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7241 FactorSum = Uaddo.
getReg(0);
7242 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7243 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7247 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7248 for (
unsigned i = 2; i < Factors.
size(); ++i)
7249 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7252 CarrySumPrevDstIdx = CarrySum;
7253 DstRegs[DstIdx] = FactorSum;
7265 LLT DstType = MRI.getType(DstReg);
7267 if (DstType.isVector())
7270 unsigned Opcode =
MI.getOpcode();
7271 unsigned OpO, OpE, OpF;
7273 case TargetOpcode::G_SADDO:
7274 case TargetOpcode::G_SADDE:
7275 case TargetOpcode::G_UADDO:
7276 case TargetOpcode::G_UADDE:
7277 case TargetOpcode::G_ADD:
7278 OpO = TargetOpcode::G_UADDO;
7279 OpE = TargetOpcode::G_UADDE;
7280 OpF = TargetOpcode::G_UADDE;
7281 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7282 OpF = TargetOpcode::G_SADDE;
7284 case TargetOpcode::G_SSUBO:
7285 case TargetOpcode::G_SSUBE:
7286 case TargetOpcode::G_USUBO:
7287 case TargetOpcode::G_USUBE:
7288 case TargetOpcode::G_SUB:
7289 OpO = TargetOpcode::G_USUBO;
7290 OpE = TargetOpcode::G_USUBE;
7291 OpF = TargetOpcode::G_USUBE;
7292 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7293 OpF = TargetOpcode::G_SSUBE;
7300 unsigned NumDefs =
MI.getNumExplicitDefs();
7301 Register Src1 =
MI.getOperand(NumDefs).getReg();
7302 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7305 CarryDst =
MI.getOperand(1).getReg();
7306 if (
MI.getNumOperands() == NumDefs + 3)
7307 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7309 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7310 LLT LeftoverTy, DummyTy;
7312 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7317 int NarrowParts = Src1Regs.
size();
7318 Src1Regs.
append(Src1Left);
7319 Src2Regs.
append(Src2Left);
7322 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7324 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7327 if (i == e - 1 && CarryDst)
7328 CarryOut = CarryDst;
7330 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7333 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7334 {Src1Regs[i], Src2Regs[i]});
7335 }
else if (i == e - 1) {
7336 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7337 {Src1Regs[i], Src2Regs[i], CarryIn});
7339 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7340 {Src1Regs[i], Src2Regs[i], CarryIn});
7346 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7347 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7348 ArrayRef(DstRegs).drop_front(NarrowParts));
7350 MI.eraseFromParent();
7356 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7358 LLT Ty = MRI.getType(DstReg);
7362 unsigned Size = Ty.getSizeInBits();
7364 if (
Size % NarrowSize != 0)
7367 unsigned NumParts =
Size / NarrowSize;
7368 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7369 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7375 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7379 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7380 MI.eraseFromParent();
7390 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7393 LLT SrcTy = MRI.getType(Src);
7404 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7417 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7420 if (SizeOp1 % NarrowSize != 0)
7422 int NumParts = SizeOp1 / NarrowSize;
7425 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7429 uint64_t OpStart =
MI.getOperand(2).getImm();
7430 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7431 for (
int i = 0; i < NumParts; ++i) {
7432 unsigned SrcStart = i * NarrowSize;
7434 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7437 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7445 int64_t ExtractOffset;
7447 if (OpStart < SrcStart) {
7449 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7451 ExtractOffset = OpStart - SrcStart;
7452 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7456 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7458 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7459 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7466 if (MRI.getType(DstReg).isVector())
7467 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7468 else if (DstRegs.
size() > 1)
7469 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7472 MI.eraseFromParent();
7484 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7486 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7489 SrcRegs.
append(LeftoverRegs);
7493 uint64_t OpStart =
MI.getOperand(3).getImm();
7494 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7495 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7496 unsigned DstStart =
I * NarrowSize;
7498 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7506 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7508 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7512 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7520 int64_t ExtractOffset, InsertOffset;
7522 if (OpStart < DstStart) {
7524 ExtractOffset = DstStart - OpStart;
7525 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7527 InsertOffset = OpStart - DstStart;
7530 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7534 if (ExtractOffset != 0 || SegSize != OpSize) {
7536 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7537 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7540 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7541 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7549 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7552 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7554 MI.eraseFromParent();
7562 LLT DstTy = MRI.getType(DstReg);
7564 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7570 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7571 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7575 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7576 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7579 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7580 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7581 {Src0Regs[I], Src1Regs[I]});
7585 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7588 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7589 DstLeftoverRegs.
push_back(Inst.getReg(0));
7592 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7593 LeftoverTy, DstLeftoverRegs);
7595 MI.eraseFromParent();
7605 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7607 LLT DstTy = MRI.getType(DstReg);
7612 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7613 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7614 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7616 MI.eraseFromParent();
7626 Register CondReg =
MI.getOperand(1).getReg();
7627 LLT CondTy = MRI.getType(CondReg);
7628 if (CondTy.isVector())
7632 LLT DstTy = MRI.getType(DstReg);
7638 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7639 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7643 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7644 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7647 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7649 CondReg, Src1Regs[
I], Src2Regs[
I]);
7653 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7655 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7659 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7660 LeftoverTy, DstLeftoverRegs);
7662 MI.eraseFromParent();
7672 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7675 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7676 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7679 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7681 auto C_0 =
B.buildConstant(NarrowTy, 0);
7683 UnmergeSrc.getReg(1), C_0);
7684 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7685 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7686 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7687 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7688 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7689 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7691 MI.eraseFromParent();
7704 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7707 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7708 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7711 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7713 auto C_0 =
B.buildConstant(NarrowTy, 0);
7715 UnmergeSrc.getReg(0), C_0);
7716 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7717 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7718 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7719 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7720 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7721 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7723 MI.eraseFromParent();
7736 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7739 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7744 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7748 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7749 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7757 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7758 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7761 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7762 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7764 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7766 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7768 MI.eraseFromParent();
7778 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7781 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7782 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7784 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7785 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7786 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7788 MI.eraseFromParent();
7803 LLT ExpTy = MRI.getType(ExpReg);
7808 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7809 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7810 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7811 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7813 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7815 MI.getOperand(2).setReg(Trunc.getReg(0));
7822 unsigned Opc =
MI.getOpcode();
7825 auto QAction = LI.getAction(Q).Action;
7831 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7834 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7838 case TargetOpcode::G_CTLZ: {
7839 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7840 unsigned Len = SrcTy.getScalarSizeInBits();
7842 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7844 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7845 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7848 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7849 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7850 MI.eraseFromParent();
7866 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7867 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7870 Op = MIBOp.getReg(0);
7875 MI.eraseFromParent();
7878 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7881 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7885 case TargetOpcode::G_CTTZ: {
7886 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7888 unsigned Len = SrcTy.getScalarSizeInBits();
7889 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
7892 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
7893 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7896 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7897 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7898 MI.eraseFromParent();
7905 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7906 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7908 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7909 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7910 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7911 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7914 MI.eraseFromParent();
7918 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7919 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7923 case TargetOpcode::G_CTPOP: {
7925 LLT Ty = MRI.getType(SrcReg);
7926 unsigned Size = Ty.getScalarSizeInBits();
7938 auto C_1 =
B.buildConstant(Ty, 1);
7939 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7941 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7942 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7943 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7947 auto C_2 =
B.buildConstant(Ty, 2);
7948 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7950 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7951 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7952 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7953 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7960 auto C_4 =
B.buildConstant(Ty, 4);
7961 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7962 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7964 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7965 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7967 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
7970 if (
Size == 16 && !Ty.isVector()) {
7972 auto C_8 =
B.buildConstant(Ty, 8);
7973 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
7974 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
7975 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
7976 MI.eraseFromParent();
7985 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7987 auto IsMulSupported = [
this](
const LLT Ty) {
7988 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7991 if (IsMulSupported(Ty)) {
7992 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7993 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7995 auto ResTmp = B8Count;
7996 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7997 auto ShiftC =
B.buildConstant(Ty, Shift);
7998 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7999 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8001 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8003 MI.eraseFromParent();
8006 case TargetOpcode::G_CTLS: {
8007 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8011 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8012 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8014 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8020 MI.eraseFromParent();
8041 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8042 LLT Ty = MRI.getType(Dst);
8043 LLT ShTy = MRI.getType(Z);
8050 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8051 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8056 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8057 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8061 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8074 MI.eraseFromParent();
8080 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8081 LLT Ty = MRI.getType(Dst);
8082 LLT ShTy = MRI.getType(Z);
8085 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8095 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8096 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8097 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8098 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8099 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8103 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8106 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8109 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8111 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8112 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8113 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8116 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8118 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8120 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8123 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8124 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8129 MI.eraseFromParent();
8140 LLT Ty = MRI.getType(Dst);
8141 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8143 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8144 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8147 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8148 return lowerFunnelShiftAsShifts(
MI);
8152 if (Result == UnableToLegalize)
8153 return lowerFunnelShiftAsShifts(
MI);
8158 auto [Dst, Src] =
MI.getFirst2Regs();
8159 LLT DstTy = MRI.getType(Dst);
8160 LLT SrcTy = MRI.getType(Src);
8164 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8172 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8176 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8180 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8185 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8186 {UnmergeSrc.getReg(0)});
8187 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8188 {UnmergeSrc.getReg(1)});
8191 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8193 MI.eraseFromParent();
8210 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8214 LLT DstTy = MRI.getType(DstReg);
8215 LLT SrcTy = MRI.getType(SrcReg);
8223 SrcTy.getElementCount().divideCoefficientBy(2));
8236 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8248 MI.eraseFromParent();
8257 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8258 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8259 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8260 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8261 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8262 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8263 MI.eraseFromParent();
8268 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8270 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8271 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8276 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8277 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8279 return lowerRotateWithReverseRotate(
MI);
8282 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8283 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8284 bool IsFShLegal =
false;
8285 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8286 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8290 MI.eraseFromParent();
8295 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8298 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8303 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8304 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8305 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8311 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8312 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8314 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8320 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8321 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8323 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8325 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8330 MI.eraseFromParent();
8338 auto [Dst, Src] =
MI.getFirst2Regs();
8343 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8371 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8384 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8388 MI.eraseFromParent();
8396 auto [Dst, Src] =
MI.getFirst2Regs();
8401 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8414 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8416 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8421 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8423 MI.eraseFromParent();
8431 auto [Dst, Src] =
MI.getFirst2Regs();
8435 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8446 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8447 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8449 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8456 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8457 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8458 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8460 MI.eraseFromParent();
8471 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8472 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8478 MI.eraseFromParent();
8483 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8486 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8487 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8488 MIRBuilder.buildSelect(Dst, Src, True, False);
8489 MI.eraseFromParent();
8493 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8513 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8520 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8521 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8522 MIRBuilder.buildSelect(Dst, Src, True, False);
8523 MI.eraseFromParent();
8527 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8533 if (DstTy.getScalarSizeInBits() == 32) {
8540 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8541 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8543 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8550 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8551 MI.eraseFromParent();
8559 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8563 if (SrcTy !=
S64 && SrcTy !=
S32)
8565 if (DstTy !=
S32 && DstTy !=
S64)
8592 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8594 MI.eraseFromParent();
8599 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8604 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8611 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8613 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8614 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8616 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8617 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8619 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8621 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8622 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8623 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8626 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8627 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8628 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8630 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8633 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8638 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8639 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8645 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8647 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8648 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8650 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8655 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8656 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8658 MI.eraseFromParent();
8664 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8666 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8667 unsigned SatWidth = DstTy.getScalarSizeInBits();
8671 APInt MinInt, MaxInt;
8694 if (AreExactFloatBounds) {
8696 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8699 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8701 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8710 MI.eraseFromParent();
8715 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8720 MI.eraseFromParent();
8727 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8735 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8745 MI.eraseFromParent();
8751 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8755 MI.eraseFromParent();
8762 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8763 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8764 "Only G_FPEXT and G_FPTRUNC are expected");
8766 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8771 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8773 StoreOpc = TargetOpcode::G_STORE;
8774 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8777 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8778 LoadOpc = TargetOpcode::G_LOAD;
8787 StackTy, StackTyAlign);
8788 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8791 StackTy, StackTyAlign);
8792 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8794 MI.eraseFromParent();
8802 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8803 assert(SrcTy.getScalarType().isBFloat16() &&
8804 "expected a bf16 source for bf16 fpext lowering");
8815 if (DstTy.getScalarType().isFloat32())
8820 MI.eraseFromParent();
8825 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8826 if (SrcTy.getScalarType().isBFloat16() &&
8827 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8839 auto [Dst, Src] =
MI.getFirst2Regs();
8843 if (MRI.getType(Src).isVector())
8847 unsigned Flags =
MI.getFlags();
8850 MI.eraseFromParent();
8854 const unsigned ExpMask = 0x7ff;
8855 const unsigned ExpBiasf64 = 1023;
8856 const unsigned ExpBiasf16 = 15;
8858 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8868 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8875 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8877 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8879 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8883 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8885 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8887 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8888 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8896 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8897 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
8908 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
8919 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
8935 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
8945 MI.eraseFromParent();
8952 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8960 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
8986 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
8988 MI.eraseFromParent();
8994 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8995 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
8998 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9005 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9006 LLT Ty = MRI.getType(Dst);
9008 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9009 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9010 MI.eraseFromParent();
9015 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9016 LLT Ty = MRI.getType(Src);
9017 auto Flags =
MI.getFlags();
9025 FracToUse = FracPart.getReg(0);
9027 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9031 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9033 FracToUse =
Select.getReg(0);
9036 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9039 MI.eraseFromParent();
9045 case TargetOpcode::G_SMIN:
9047 case TargetOpcode::G_SMAX:
9049 case TargetOpcode::G_UMIN:
9051 case TargetOpcode::G_UMAX:
9059 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9064 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9065 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9067 MI.eraseFromParent();
9076 LLT DstTy = MRI.getType(Dst);
9077 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9087 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9088 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9090 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9093 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9094 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9095 if (TLI.preferSelectsOverBooleanArithmetic(
9098 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9099 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9101 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9102 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9108 unsigned BoolExtOp =
9110 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9111 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9115 MI.eraseFromParent();
9121 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9122 const int Src0Size = Src0Ty.getScalarSizeInBits();
9123 const int Src1Size = Src1Ty.getScalarSizeInBits();
9133 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9134 Src0Ty.getScalarType().isInteger()))
9135 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9137 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9138 Src1Ty.getScalarType().isInteger()))
9139 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9144 auto NotSignBitMask =
MIRBuilder.buildConstant(
9148 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9150 if (Src0Ty == Src1Ty) {
9151 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9152 }
else if (Src0Size > Src1Size) {
9153 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9154 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9155 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9156 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
9158 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9159 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9160 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9161 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9167 unsigned Flags =
MI.getFlags();
9172 if (DstTy == DstIntTy)
9173 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9179 MI.eraseFromParent();
9190 switch (
MI.getOpcode()) {
9191 case TargetOpcode::G_FMINNUM:
9192 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9194 case TargetOpcode::G_FMINIMUMNUM:
9195 NewOp = TargetOpcode::G_FMINNUM;
9197 case TargetOpcode::G_FMAXNUM:
9198 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9200 case TargetOpcode::G_FMAXIMUMNUM:
9201 NewOp = TargetOpcode::G_FMAXNUM;
9207 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9208 LLT Ty = MRI.getType(Dst);
9217 if (!VT->isKnownNeverSNaN(Src0))
9218 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9220 if (!VT->isKnownNeverSNaN(Src1))
9221 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9226 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9227 MI.eraseFromParent();
9233 unsigned Opc =
MI.getOpcode();
9234 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9235 LLT Ty = MRI.getType(Dst);
9238 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9240 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9241 unsigned OpcNonIeee =
9242 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9243 bool MinMaxMustRespectOrderedZero =
false;
9247 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9249 MinMaxMustRespectOrderedZero =
true;
9250 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9255 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9260 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9263 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9267 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9269 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9279 const unsigned Flags =
MI.getFlags();
9285 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9287 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9289 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9291 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9293 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9298 MI.eraseFromParent();
9305 LLT Ty = MRI.getType(DstReg);
9306 unsigned Flags =
MI.getFlags();
9311 MI.eraseFromParent();
9317 auto [DstReg,
X] =
MI.getFirst2Regs();
9318 const unsigned Flags =
MI.getFlags();
9319 const LLT Ty = MRI.getType(DstReg);
9331 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9333 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9338 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9339 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9340 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9341 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9343 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9345 MI.eraseFromParent();
9350 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9351 unsigned Flags =
MI.getFlags();
9352 LLT Ty = MRI.getType(DstReg);
9359 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9360 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9363 SrcReg, Zero, Flags);
9365 SrcReg, Trunc, Flags);
9369 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9370 MI.eraseFromParent();
9376 const unsigned NumOps =
MI.getNumOperands();
9377 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9378 unsigned PartSize = Src0Ty.getSizeInBits();
9383 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9384 const unsigned Offset = (
I - 1) * PartSize;
9387 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9390 MRI.createGenericVirtualRegister(WideTy);
9393 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9394 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9395 ResultReg = NextResult;
9398 if (DstTy.isPointer()) {
9399 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9400 DstTy.getAddressSpace())) {
9408 MI.eraseFromParent();
9414 const unsigned NumDst =
MI.getNumOperands() - 1;
9415 Register SrcReg =
MI.getOperand(NumDst).getReg();
9416 Register Dst0Reg =
MI.getOperand(0).getReg();
9417 LLT DstTy = MRI.getType(Dst0Reg);
9426 LLT IntTy = MRI.getType(SrcReg);
9431 unsigned Offset = DstSize;
9432 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9434 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9438 MI.eraseFromParent();
9457 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9458 InsertVal =
MI.getOperand(2).getReg();
9460 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9462 LLT VecTy = MRI.getType(SrcVec);
9472 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9473 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9475 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9478 MI.eraseFromParent();
9483 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9494 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9501 int64_t
Offset = IdxVal * EltBytes;
9512 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9515 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9517 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9520 MI.eraseFromParent();
9526 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9527 MI.getFirst3RegLLTs();
9537 for (
int Idx : Mask) {
9539 if (!
Undef.isValid())
9545 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9547 int NumElts = Src0Ty.getNumElements();
9548 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9549 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9550 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9552 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9554 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9559 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9560 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9561 MI.eraseFromParent();
9567 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9568 MI.getFirst4RegLLTs();
9570 if (VecTy.isScalableVector())
9586 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9589 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9592 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9595 std::optional<APInt> PassthruSplatVal =
9598 if (PassthruSplatVal.has_value()) {
9600 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9601 }
else if (HasPassthru) {
9602 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9603 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9609 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9613 unsigned NumElmts = VecTy.getNumElements();
9614 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9616 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9619 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9622 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9627 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9629 if (HasPassthru &&
I == NumElmts - 1) {
9632 auto AllLanesSelected =
MIRBuilder.buildICmp(
9634 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9635 {OutPos, EndOfVector});
9639 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9641 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9646 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9648 MI.eraseFromParent();
9665 if (Alignment >
Align(1)) {
9677 const auto &MF = *
MI.getMF();
9683 Register AllocSize =
MI.getOperand(1).getReg();
9686 LLT PtrTy = MRI.getType(Dst);
9687 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9694 MI.eraseFromParent();
9700 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9705 MI.eraseFromParent();
9711 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9716 MI.eraseFromParent();
9722 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9723 unsigned Offset =
MI.getOperand(2).getImm();
9726 if (SrcTy.isVector()) {
9727 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9728 unsigned DstSize = DstTy.getSizeInBits();
9730 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9731 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9733 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9737 for (
unsigned Idx =
Offset / SrcEltSize;
9738 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9739 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9741 if (SubVectorElts.
size() == 1)
9742 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9744 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9746 MI.eraseFromParent();
9752 if ((SrcTy.isPointer() &&
9753 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9754 (DstTy.isPointer() &&
9755 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9756 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9760 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9761 (SrcTy.isScalar() || SrcTy.isPointer() ||
9762 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9763 LLT SrcIntTy = SrcTy;
9764 if (!SrcTy.isScalar()) {
9766 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9770 if (DstTy.isPointer())
9772 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9778 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9782 if (DstTy.isPointer())
9785 MI.eraseFromParent();
9793 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9796 LLT DstTy = MRI.getType(Src);
9797 LLT InsertTy = MRI.getType(InsertSrc);
9800 bool IsNonIntegralInsert =
9810 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9811 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9818 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9820 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9824 for (; Idx <
Offset / EltSize; ++Idx) {
9825 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9830 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9831 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9833 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9837 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
9839 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
9846 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9849 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9850 MI.eraseFromParent();
9859 if (IsNonIntegralDst || IsNonIntegralInsert) {
9860 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9864 LLT IntDstTy = DstTy;
9868 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9873 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9879 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9885 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9886 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9887 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9890 MI.eraseFromParent();
9896 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9897 MI.getFirst4RegLLTs();
9898 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9901 LLT BoolTy = Dst1Ty;
9903 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9918 auto ResultLowerThanLHS =
9922 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
9926 auto LHSLessThanRHS =
9928 auto ResultNegative =
9930 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
9934 MI.eraseFromParent();
9940 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9941 const LLT Ty = MRI.getType(Res);
9944 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9945 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9946 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9957 MI.eraseFromParent();
9962 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9963 const LLT Ty = MRI.getType(Res);
9966 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9967 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9968 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9973 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9978 MI.eraseFromParent();
9984 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9985 LLT Ty = MRI.getType(Res);
9989 switch (
MI.getOpcode()) {
9992 case TargetOpcode::G_UADDSAT:
9995 BaseOp = TargetOpcode::G_ADD;
9997 case TargetOpcode::G_SADDSAT:
10000 BaseOp = TargetOpcode::G_ADD;
10002 case TargetOpcode::G_USUBSAT:
10005 BaseOp = TargetOpcode::G_SUB;
10007 case TargetOpcode::G_SSUBSAT:
10010 BaseOp = TargetOpcode::G_SUB;
10025 uint64_t NumBits = Ty.getScalarSizeInBits();
10032 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10036 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10044 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10049 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10050 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10053 MI.eraseFromParent();
10059 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10060 LLT Ty = MRI.getType(Res);
10064 unsigned OverflowOp;
10065 switch (
MI.getOpcode()) {
10068 case TargetOpcode::G_UADDSAT:
10071 OverflowOp = TargetOpcode::G_UADDO;
10073 case TargetOpcode::G_SADDSAT:
10076 OverflowOp = TargetOpcode::G_SADDO;
10078 case TargetOpcode::G_USUBSAT:
10081 OverflowOp = TargetOpcode::G_USUBO;
10083 case TargetOpcode::G_SSUBSAT:
10086 OverflowOp = TargetOpcode::G_SSUBO;
10091 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10092 Register Tmp = OverflowRes.getReg(0);
10093 Register Ov = OverflowRes.getReg(1);
10102 uint64_t NumBits = Ty.getScalarSizeInBits();
10103 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10104 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10107 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10115 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10117 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10119 MI.eraseFromParent();
10125 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10126 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10127 "Expected shlsat opcode!");
10128 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10129 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10130 LLT Ty = MRI.getType(Res);
10134 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10135 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10144 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10149 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10151 MI.eraseFromParent();
10156 auto [Dst, Src] =
MI.getFirst2Regs();
10157 const LLT Ty = MRI.getType(Src);
10158 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10159 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10162 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10163 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10164 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10165 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10168 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10171 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10172 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10174 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10175 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10176 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10178 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10179 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10180 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10182 Res.getInstr()->getOperand(0).setReg(Dst);
10184 MI.eraseFromParent();
10191 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10194 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10195 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10196 return B.buildOr(Dst,
LHS,
RHS);
10201 auto [Dst, Src] =
MI.getFirst2Regs();
10202 const LLT SrcTy = MRI.getType(Src);
10203 unsigned Size = SrcTy.getScalarSizeInBits();
10204 unsigned VSize = SrcTy.getSizeInBits();
10207 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10208 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10209 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10210 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10215 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10216 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10217 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10221 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10244 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10248 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10251 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10255 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10259 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10264 MI.eraseFromParent();
10272 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10273 int NameOpIdx = IsRead ? 1 : 0;
10274 int ValRegIndex = IsRead ? 0 : 1;
10276 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10277 const LLT Ty = MRI.getType(ValReg);
10279 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10286 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10287 Fn,
MI.getDebugLoc()));
10291 MI.eraseFromParent();
10300 MI.eraseFromParent();
10306 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10307 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10308 Register Result =
MI.getOperand(0).getReg();
10309 LLT OrigTy = MRI.getType(Result);
10313 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10314 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10316 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10318 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10319 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10322 MI.eraseFromParent();
10328 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10333 MI.eraseFromParent();
10338 MI.eraseFromParent();
10345 unsigned BitSize = SrcTy.getScalarSizeInBits();
10349 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10356 APInt ExpMask = Inf;
10358 APInt QNaNBitMask =
10362 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10363 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10364 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10365 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10366 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10368 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10372 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10374 LLT DstTyCopy = DstTy;
10376 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10404 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10407 Mask &= ~PartialCheck;
10416 else if (PartialCheck ==
fcZero)
10428 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10429 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10430 auto SubnormalRes =
10432 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10434 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10435 appendToRes(SubnormalRes);
10442 else if (PartialCheck ==
fcInf)
10447 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10454 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10455 if (PartialCheck ==
fcNan) {
10459 }
else if (PartialCheck ==
fcQNan) {
10469 Abs, InfWithQnanBitC);
10470 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10477 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10479 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10480 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10483 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10485 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10488 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10489 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10491 appendToRes(NormalRes);
10495 MI.eraseFromParent();
10501 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10502 MI.getFirst4RegLLTs();
10511 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10512 Op1Ty = MRI.getType(Op1Reg);
10513 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10514 Op2Ty = MRI.getType(Op2Reg);
10518 if (MaskTy.isScalar()) {
10526 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10529 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10531 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10533 if (DstTy.isVector()) {
10535 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10536 MaskReg = ShufSplat.getReg(0);
10540 }
else if (!DstTy.isVector()) {
10545 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10549 if (!Op1Ty.getScalarType().isAnyScalar() &&
10550 !Op1Ty.getScalarType().isInteger())
10551 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10553 if (!Op2Ty.getScalarType().isAnyScalar() &&
10554 !Op2Ty.getScalarType().isInteger()) {
10556 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10557 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10560 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10561 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10562 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10567 if (DstTy == Op1TyInt)
10570 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10574 MI.eraseFromParent();
10580 unsigned Opcode =
MI.getOpcode();
10583 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10584 : TargetOpcode::G_UDIV,
10585 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10587 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10588 : TargetOpcode::G_UREM,
10589 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10590 MI.eraseFromParent();
10600 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10604 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10607 MI.eraseFromParent();
10617 Register SrcReg =
MI.getOperand(1).getReg();
10618 LLT Ty = MRI.getType(SrcReg);
10619 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10622 MI.eraseFromParent();
10628 Register SrcReg =
MI.getOperand(1).getReg();
10629 Register DestReg =
MI.getOperand(0).getReg();
10631 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10632 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10635 MI.eraseFromParent();
10641 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10642 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10643 "Expected G_ABDS or G_ABDU instruction");
10645 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10646 LLT Ty = MRI.getType(LHS);
10656 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10658 MI.eraseFromParent();
10664 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10665 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10666 "Expected G_ABDS or G_ABDU instruction");
10668 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10669 LLT Ty = MRI.getType(LHS);
10674 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10675 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10676 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10678 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10679 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10681 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10683 MI.eraseFromParent();
10688 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10693 if (!(SrcTy.getScalarType().isAnyScalar() ||
10694 SrcTy.getScalarType().isInteger())) {
10696 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10697 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10700 if (MRI.getType(DstReg) != TyInt) {
10704 .buildAnd(TyInt, CastedSrc,
10707 DstTy.getScalarSizeInBits())))
10719 MI.eraseFromParent();
10725 Register SrcReg =
MI.getOperand(1).getReg();
10726 LLT SrcTy = MRI.getType(SrcReg);
10727 LLT DstTy = MRI.getType(SrcReg);
10730 if (SrcTy.isScalar()) {
10735 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10746 Register ListPtr =
MI.getOperand(1).getReg();
10747 LLT PtrTy = MRI.getType(ListPtr);
10754 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10756 const Align A(
MI.getOperand(2).getImm());
10758 if (
A > TLI.getMinStackArgumentAlignment()) {
10760 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10761 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10762 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10763 VAList = AndDst.getReg(0);
10770 LLT LLTTy = MRI.getType(Dst);
10773 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10774 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10779 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10781 Align EltAlignment =
DL.getABITypeAlign(Ty);
10784 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10786 MI.eraseFromParent();
10791 [[maybe_unused]]
unsigned OpCode =
MI.getOpcode();
10792 assert((OpCode == TargetOpcode::G_SMULFIX ||
10793 OpCode == TargetOpcode::G_UMULFIX) &&
10794 "Operator must be either G_SMULFIX or G_UMULFIX!");
10795 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10796 LLT Ty = MRI.getType(Dst);
10797 unsigned Scale =
MI.getOperand(3).getImm();
10801 MI.eraseFromParent();
10807 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
10809 if (
MI.getOpcode() == TargetOpcode::G_SMULFIX) {
10818 if (
MI.getOpcode() == TargetOpcode::G_SMULFIX)
10825 MI.eraseFromParent();
10832 unsigned NumBits = Ty.getScalarSizeInBits();
10834 if (!Ty.isVector() && ValVRegAndVal) {
10835 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10843 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10864 uint64_t KnownLen,
Align Alignment,
10866 auto &MF = *
MI.getParent()->getParent();
10871 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10872 assert(!MemOps.
empty() &&
"Expected at least one memory op");
10875 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10876 const auto &DstMMO = **
MI.memoperands_begin();
10878 if (DstAlignCanChange) {
10881 Align NewAlign =
DL.getABITypeAlign(IRTy);
10882 if (NewAlign > Alignment) {
10883 Alignment = NewAlign;
10891 MachineIRBuilder MIB(
MI);
10893 LLT LargestTy = MemOps[0];
10894 for (
unsigned i = 1; i < MemOps.
size(); i++)
10896 LargestTy = MemOps[i];
10908 LLT PtrTy = MRI.getType(Dst);
10909 unsigned DstOff = 0;
10910 unsigned Size = KnownLen;
10911 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
10912 LLT Ty = MemOps[
I];
10915 if (TySize >
Size) {
10919 DstOff -= TySize -
Size;
10929 TLI.isTruncateFree(LargestVT, VT))
10930 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10943 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10946 MIB.buildStore(
Value, Ptr, *StoreMMO);
10951 MI.eraseFromParent();
10957 uint64_t KnownLen,
Align Alignment,
10959 auto &MF = *
MI.getParent()->getParent();
10963 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10964 assert(!MemOps.
empty() &&
"Expected at least one memory op");
10967 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10973 const auto &DstMMO = **
MI.memoperands_begin();
10974 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10976 if (DstAlignCanChange) {
10979 Align NewAlign =
DL.getABITypeAlign(IRTy);
10984 if (!
TRI->hasStackRealignment(MF))
10985 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10986 NewAlign = std::min(NewAlign, *StackAlign);
10988 if (NewAlign > Alignment) {
10989 Alignment = NewAlign;
10997 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10999 MachineIRBuilder MIB(
MI);
11005 unsigned CurrOffset = 0;
11006 unsigned Size = KnownLen;
11007 for (
auto CopyTy : MemOps) {
11008 TypeSize TySize = CopyTy.getSizeInBytes();
11012 if (TySize >
Size) {
11013 unsigned Overlap = TySize -
Size;
11014 assert(Overlap < CurrOffset &&
11015 "overlapping memcpy load/store spans the whole region or more");
11016 CurrOffset -= Overlap;
11026 if (CurrOffset != 0) {
11027 LLT SrcTy = MRI.getType(Src);
11031 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11033 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11037 if (CurrOffset != 0) {
11038 LLT DstTy = MRI.getType(Dst);
11039 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11041 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11042 CurrOffset += TySize;
11046 MI.eraseFromParent();
11052 uint64_t KnownLen,
Align Alignment,
11054 auto &MF = *
MI.getParent()->getParent();
11058 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11059 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11062 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11063 const auto &DstMMO = **
MI.memoperands_begin();
11064 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11066 if (DstAlignCanChange) {
11069 Align NewAlign =
DL.getABITypeAlign(IRTy);
11074 if (!
TRI->hasStackRealignment(MF))
11075 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11076 NewAlign = std::min(NewAlign, *StackAlign);
11078 if (NewAlign > Alignment) {
11079 Alignment = NewAlign;
11087 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11089 MachineIRBuilder MIB(
MI);
11093 unsigned CurrOffset = 0;
11094 unsigned Size = KnownLen;
11095 SmallVector<Register, 16> LoadVals;
11096 for (
auto CopyTy : MemOps) {
11097 TypeSize TySize = CopyTy.getSizeInBytes();
11101 if (TySize >
Size) {
11102 unsigned Overlap = TySize -
Size;
11103 assert(Overlap < CurrOffset &&
11104 "overlapping memmove load spans the whole region or more");
11105 CurrOffset -= Overlap;
11113 if (CurrOffset != 0) {
11114 LLT SrcTy = MRI.getType(Src);
11117 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11119 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11120 CurrOffset += TySize;
11126 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11127 LLT CopyTy = MemOps[
I];
11132 if (TySize >
Size) {
11133 unsigned Overlap = TySize -
Size;
11134 assert(Overlap < CurrOffset &&
11135 "overlapping memmove store spans the whole region or more");
11136 CurrOffset -= Overlap;
11143 if (CurrOffset != 0) {
11144 LLT DstTy = MRI.getType(Dst);
11147 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11149 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11150 CurrOffset += TySize;
11153 MI.eraseFromParent();
11160 const unsigned Opc =
MI.getOpcode();
11161 assert((
Opc == TargetOpcode::G_MEMCPY ||
11162 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11163 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11164 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11165 "Expected memcpy like instruction");
11167 if (KnownLen == 0) {
11168 MI.eraseFromParent();
11172 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11173 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11176 if (
Opc == TargetOpcode::G_MEMMOVE)
11177 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11179 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11180 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11190 bool DstAlignCanChange;
11191 std::vector<LLT> MemOps;
11193 DstAlignCanChange, MemOps))
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")
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 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 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 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")
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.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
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)
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.
Register getValueReg() const
Get the stored value register.
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.
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.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
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.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr ElementCount getElementCount() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
constexpr LLT changeVectorElementType(LLT NewEltTy) const
Returns a vector with the same number of elements but the new element type.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLT changeVectorElementCount(ElementCount EC) const
Return a vector with the same element type and the new element count.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
static LLT floatIEEE(unsigned SizeInBits)
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.
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 LegalizeResult lowerFPEXT_BF16(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 LegalizerHelper::LegalizeResult createAtomicLibcall(MachineInstr &MI) const
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 lowerFPEXT(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 LegalizeResult lowerMemCpyFamily(MachineInstr &MI, Register Dst, Register Src, uint64_t KnownLen, Align Alignment, bool DstAlignCanChange, ArrayRef< LLT > MemOps)
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 lowerFPExtAndTruncMem(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 void widenScalarSrcUsingFPExt(MachineInstr &MI, LLT WideTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
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)
LLVM_ABI LegalizeResult lowerFMODF(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 lowerFPTRUNC_F32_TO_BF16(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 LegalizeResult lowerMulfix(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 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)
LLVM_ABI void widenScalarDstUsingFPTrunc(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
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 Register coerceToInteger(Register Val)
Cast the given value to an LLT::integer with an equivalent size.
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.
LLVM_ABI StringRef getString() const
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
LLVM_ABI iterator getFirstTerminatorForward()
Finds the first terminator in a block by scanning forward.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
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.
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.
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.
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 & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
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.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool 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
Represent a constant reference to a string, i.e.
constexpr const char * data() const
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.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
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.
@ 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.
@ 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.
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(Register Def, const MachineRegisterInfo &MRI)
Determines if Def defines a constant integer or a splat vector of constant integers.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
@ Undef
Value of the register doesn't matter.
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 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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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...
@ Success
The lock was released successfully.
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
LLVM_ABI bool canLowerMemCpyFamily(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned MaxLen, Register &Dst, Register &Src, uint64_t &KnownLen, Align &Alignment, bool &DstAlignCanChange, std::vector< LLT > &MemOps)
Matcher for memcpy-like instructions.
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool 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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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.
@ Custom
The result value requires a custom uniformity check.
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,...
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.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.