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();
3648 auto Unmerge =
B.buildUnmerge(Ty, Src);
3649 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3658 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3672 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3681 MI.eraseFromParent();
3692 MI.eraseFromParent();
3699 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3700 if (SrcTy.isVector()) {
3704 if (DstTy.isVector()) {
3705 int NumDstElt = DstTy.getNumElements();
3706 int NumSrcElt = SrcTy.getNumElements();
3709 LLT DstCastTy = DstEltTy;
3710 LLT SrcPartTy = SrcEltTy;
3714 if (NumSrcElt < NumDstElt) {
3725 SrcPartTy = SrcEltTy;
3726 }
else if (NumSrcElt > NumDstElt) {
3738 DstCastTy = DstEltTy;
3743 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3747 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3748 MI.eraseFromParent();
3752 if (DstTy.isVector()) {
3755 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3756 MI.eraseFromParent();
3772 unsigned NewEltSize,
3773 unsigned OldEltSize) {
3774 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3775 LLT IdxTy =
B.getMRI()->getType(Idx);
3778 auto OffsetMask =
B.buildConstant(
3780 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3781 return B.buildShl(IdxTy, OffsetIdx,
3782 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3797 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3801 unsigned OldNumElts = SrcVecTy.getNumElements();
3808 if (NewNumElts > OldNumElts) {
3819 if (NewNumElts % OldNumElts != 0)
3823 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3827 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3830 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3832 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3833 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3834 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3835 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3836 NewOps[
I] = Elt.getReg(0);
3839 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3841 MI.eraseFromParent();
3845 if (NewNumElts < OldNumElts) {
3846 if (NewEltSize % OldEltSize != 0)
3868 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3869 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3872 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3876 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3877 ScaledIdx).getReg(0);
3885 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3887 MI.eraseFromParent();
3901 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3902 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3903 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3904 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3907 auto EltMask =
B.buildConstant(
3911 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3912 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3915 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3919 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3933 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3934 MI.getFirst4RegLLTs();
3946 if (NewNumElts < OldNumElts) {
3947 if (NewEltSize % OldEltSize != 0)
3956 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3957 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3960 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3964 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3965 ScaledIdx).getReg(0);
3975 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3976 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3980 MI.eraseFromParent();
4010 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4014 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4015 return UnableToLegalize;
4020 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4022 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4031 MI.eraseFromParent();
4049 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4050 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4060 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4061 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4063 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4064 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4066 MI.eraseFromParent();
4096 LLT DstTy = MRI.getType(Dst);
4097 LLT SrcTy = MRI.getType(Src);
4103 if (DstTy == CastTy)
4111 if (CastEltSize < DstEltSize)
4114 auto AdjustAmt = CastEltSize / DstEltSize;
4115 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4116 SrcTyMinElts % AdjustAmt != 0)
4121 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4122 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4125 ES->eraseFromParent();
4160 LLT DstTy = MRI.getType(Dst);
4161 LLT BigVecTy = MRI.getType(BigVec);
4162 LLT SubVecTy = MRI.getType(SubVec);
4164 if (DstTy == CastTy)
4179 if (CastEltSize < DstEltSize)
4182 auto AdjustAmt = CastEltSize / DstEltSize;
4183 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4184 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4190 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4191 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4193 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4196 ES->eraseFromParent();
4204 LLT DstTy = MRI.getType(DstReg);
4214 if (MemSizeInBits != MemStoreSizeInBits) {
4231 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4235 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4236 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4238 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4241 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4243 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4246 if (DstTy != LoadTy)
4254 if (
MIRBuilder.getDataLayout().isBigEndian())
4272 uint64_t LargeSplitSize, SmallSplitSize;
4277 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4284 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4287 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4298 if (Alignment.
value() * 8 > MemSizeInBits &&
4303 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4320 LLT PtrTy = MRI.getType(PtrReg);
4333 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4336 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4337 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4338 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4340 SmallPtr, *SmallMMO);
4342 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4343 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4345 if (AnyExtTy == DstTy)
4346 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4348 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4352 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4372 LLT SrcTy = MRI.getType(SrcReg);
4380 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4386 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4388 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4392 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4396 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4411 uint64_t LargeSplitSize, SmallSplitSize;
4418 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4421 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4430 if (SrcTy.isPointer()) {
4435 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4438 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4439 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4442 LLT PtrTy = MRI.getType(PtrReg);
4444 LargeSplitSize / 8);
4445 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4451 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4452 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4461 LLT SrcTy = MRI.getType(SrcReg);
4467 assert(SrcTy.isVector() &&
"Expect a vector store type");
4474 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4478 auto Elt =
MIRBuilder.buildExtractVectorElement(
4479 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4480 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4481 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4487 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4488 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4492 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4503 switch (
MI.getOpcode()) {
4504 case TargetOpcode::G_LOAD: {
4522 case TargetOpcode::G_STORE: {
4538 case TargetOpcode::G_SELECT: {
4542 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4544 dbgs() <<
"bitcast action not implemented for vector select\n");
4555 case TargetOpcode::G_AND:
4556 case TargetOpcode::G_OR:
4557 case TargetOpcode::G_XOR: {
4565 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4567 case TargetOpcode::G_INSERT_VECTOR_ELT:
4569 case TargetOpcode::G_CONCAT_VECTORS:
4571 case TargetOpcode::G_SHUFFLE_VECTOR:
4573 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4575 case TargetOpcode::G_INSERT_SUBVECTOR:
4583void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4592 switch(
MI.getOpcode()) {
4595 case TargetOpcode::G_FCONSTANT:
4597 case TargetOpcode::G_BITCAST:
4599 case TargetOpcode::G_SREM:
4600 case TargetOpcode::G_UREM: {
4601 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4603 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4604 {MI.getOperand(1), MI.getOperand(2)});
4606 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4608 MI.eraseFromParent();
4611 case TargetOpcode::G_SADDO:
4612 case TargetOpcode::G_SSUBO:
4614 case TargetOpcode::G_SADDE:
4616 case TargetOpcode::G_SSUBE:
4618 case TargetOpcode::G_UMULH:
4619 case TargetOpcode::G_SMULH:
4621 case TargetOpcode::G_SMULO:
4622 case TargetOpcode::G_UMULO: {
4625 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4626 LLT Ty = MRI.getType(Res);
4628 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4629 ? TargetOpcode::G_SMULH
4630 : TargetOpcode::G_UMULH;
4634 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4635 MI.removeOperand(1);
4638 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4646 if (Opcode == TargetOpcode::G_SMULH) {
4647 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4648 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4655 case TargetOpcode::G_FNEG: {
4656 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4659 Register CastedSubByReg = SubByReg;
4661 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4662 !SubByRegTy.getScalarType().isInteger()) {
4663 auto BitcastDst = SubByRegTy.changeElementType(
4665 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4671 if (ResTy != TyInt) {
4673 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4676 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4678 MI.eraseFromParent();
4681 case TargetOpcode::G_FSUB:
4682 case TargetOpcode::G_STRICT_FSUB: {
4683 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4684 LLT Ty = MRI.getType(Res);
4689 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4690 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4694 MI.eraseFromParent();
4697 case TargetOpcode::G_FMAD:
4699 case TargetOpcode::G_FFLOOR:
4701 case TargetOpcode::G_LROUND:
4702 case TargetOpcode::G_LLROUND: {
4705 LLT SrcTy = MRI.getType(SrcReg);
4706 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4709 MI.eraseFromParent();
4712 case TargetOpcode::G_INTRINSIC_ROUND:
4714 case TargetOpcode::G_FRINT: {
4717 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4720 case TargetOpcode::G_INTRINSIC_LRINT:
4721 case TargetOpcode::G_INTRINSIC_LLRINT: {
4724 LLT SrcTy = MRI.getType(SrcReg);
4726 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4728 MI.eraseFromParent();
4731 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4732 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4733 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4734 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4735 **
MI.memoperands_begin());
4737 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4738 MI.eraseFromParent();
4741 case TargetOpcode::G_LOAD:
4742 case TargetOpcode::G_SEXTLOAD:
4743 case TargetOpcode::G_ZEXTLOAD:
4745 case TargetOpcode::G_STORE:
4747 case TargetOpcode::G_CTLZ_ZERO_POISON:
4748 case TargetOpcode::G_CTTZ_ZERO_POISON:
4749 case TargetOpcode::G_CTLZ:
4750 case TargetOpcode::G_CTTZ:
4751 case TargetOpcode::G_CTPOP:
4752 case TargetOpcode::G_CTLS:
4755 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4757 Register NewRes = MRI.cloneVirtualRegister(Res);
4764 MI.eraseFromParent();
4768 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4769 const LLT CondTy = MRI.getType(CarryOut);
4770 const LLT Ty = MRI.getType(Res);
4772 Register NewRes = MRI.cloneVirtualRegister(Res);
4775 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4781 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4782 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4789 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4794 MI.eraseFromParent();
4798 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4803 MI.eraseFromParent();
4807 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4808 const LLT CondTy = MRI.getType(BorrowOut);
4809 const LLT Ty = MRI.getType(Res);
4812 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4818 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4819 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4826 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4827 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4829 MI.eraseFromParent();
4869 case G_MERGE_VALUES:
4871 case G_UNMERGE_VALUES:
4873 case TargetOpcode::G_SEXT_INREG: {
4874 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4875 int64_t SizeInBits =
MI.getOperand(2).getImm();
4877 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4878 LLT DstTy = MRI.getType(DstReg);
4879 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4882 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4883 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4884 MI.eraseFromParent();
4887 case G_EXTRACT_VECTOR_ELT:
4888 case G_INSERT_VECTOR_ELT:
4890 case G_SHUFFLE_VECTOR:
4892 case G_VECTOR_COMPRESS:
4894 case G_DYN_STACKALLOC:
4896 case G_INSERT_SUBVECTOR: {
4897 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4898 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4903 Register Subvector =
MI.getOperand(2).getReg();
4904 auto InsertionPointImm =
MI.getOperand(3).getImm();
4907 LLT SubvectorTy = MRI.getType(Subvector);
4911 bool InsertInLowHalf = InsertionPointImm == 0;
4912 auto Extract =
MIRBuilder.buildExtractSubvector(
4916 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4917 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4919 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4920 {LowHalf, HighHalf});
4921 MI.eraseFromParent();
4927 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4928 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4934 if (i >= InsertionPointImm &&
4936 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
4944 MI.eraseFromParent();
4950 case G_STACKRESTORE:
4960 case G_READ_REGISTER:
4961 case G_WRITE_REGISTER:
4968 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4969 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4975 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4980 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4991 bool IsSigned =
MI.getOpcode() == G_ABDS;
4992 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4993 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4994 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5017 case G_MEMCPY_INLINE:
5018 case G_MEMSET_INLINE:
5030 case G_ATOMICRMW_SUB: {
5031 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5032 const LLT ValTy = MRI.getType(Val);
5036 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5037 MI.eraseFromParent();
5063 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5067 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5073 Align StackTypeAlign =
5080 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5081 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5086 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5098 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
5101 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5112 "Converting bits to bytes lost precision");
5118 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5119 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5121 if (IdxTy != MRI.getType(Index))
5122 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5127 LLT PtrTy = MRI.getType(VecPtr);
5128 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5136 std::initializer_list<unsigned> NonVecOpIndices) {
5137 if (
MI.getNumMemOperands() != 0)
5154 if (!Ty.isVector()) {
5160 if (Ty.getNumElements() != NumElts)
5175 assert(Ty.isVector() &&
"Expected vector type");
5177 int NumParts, NumLeftover;
5178 std::tie(NumParts, NumLeftover) =
5181 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5182 for (
int i = 0; i < NumParts; ++i) {
5187 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5196 for (
unsigned i = 0; i <
N; ++i) {
5198 Ops.push_back(
Op.getReg());
5199 else if (
Op.isImm())
5200 Ops.push_back(
Op.getImm());
5201 else if (
Op.isPredicate())
5223 std::initializer_list<unsigned> NonVecOpIndices) {
5225 "Non-compatible opcode or not specified non-vector operands");
5226 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5228 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5229 unsigned NumDefs =
MI.getNumDefs();
5237 for (
unsigned i = 0; i < NumDefs; ++i) {
5238 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5246 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5247 ++UseIdx, ++UseNo) {
5250 MI.getOperand(UseIdx));
5259 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5263 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5265 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5266 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5269 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5270 Uses.push_back(InputOpsPieces[InputNo][i]);
5273 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5274 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5279 for (
unsigned i = 0; i < NumDefs; ++i)
5280 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5282 for (
unsigned i = 0; i < NumDefs; ++i)
5283 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5286 MI.eraseFromParent();
5293 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5295 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5296 unsigned NumDefs =
MI.getNumDefs();
5300 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5305 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5306 UseIdx += 2, ++UseNo) {
5314 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5316 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5317 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5319 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5322 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5323 Phi.addUse(InputOpsPieces[j][i]);
5324 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5334 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5336 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5339 MI.eraseFromParent();
5347 const int NumDst =
MI.getNumOperands() - 1;
5348 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5349 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5350 LLT SrcTy = MRI.getType(SrcReg);
5352 if (TypeIdx != 1 || NarrowTy == DstTy)
5359 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5362 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5376 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5377 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5378 const int PartsPerUnmerge = NumDst / NumUnmerge;
5380 for (
int I = 0;
I != NumUnmerge; ++
I) {
5381 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5383 for (
int J = 0; J != PartsPerUnmerge; ++J)
5384 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5385 MIB.addUse(Unmerge.getReg(
I));
5388 MI.eraseFromParent();
5395 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5399 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5401 if (NarrowTy == SrcTy)
5409 assert(SrcTy.isVector() &&
"Expected vector types");
5411 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5425 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5426 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5427 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5433 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5434 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5435 ++i,
Offset += NumNarrowTyElts) {
5438 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5441 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5442 MI.eraseFromParent();
5446 assert(TypeIdx == 0 &&
"Bad type index");
5447 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5462 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5463 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5465 for (
unsigned i = 0; i < NumParts; ++i) {
5467 for (
unsigned j = 0; j < NumElts; ++j)
5468 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5470 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5473 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5474 MI.eraseFromParent();
5482 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5484 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5486 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5488 InsertVal =
MI.getOperand(2).getReg();
5490 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5491 LLT VecTy = MRI.getType(SrcVec);
5497 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5501 MI.eraseFromParent();
5510 SplitPieces[IdxVal] = InsertVal;
5511 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5513 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5517 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5520 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5521 TargetOpcode::G_ANYEXT);
5525 LLT IdxTy = MRI.getType(Idx);
5526 int64_t PartIdx = IdxVal / NewNumElts;
5528 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5531 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5534 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5535 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5536 VecParts[PartIdx] = InsertPart.getReg(0);
5540 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5542 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5546 MI.eraseFromParent();
5566 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5578 LLT ValTy = MRI.getType(ValReg);
5587 int NumLeftover = -1;
5593 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5595 NumParts = NarrowRegs.
size();
5596 NumLeftover = NarrowLeftoverRegs.
size();
5603 LLT PtrTy = MRI.getType(AddrReg);
5613 auto MMO = LdStMI.
getMMO();
5615 unsigned NumParts,
unsigned Offset) ->
unsigned {
5618 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5620 unsigned ByteOffset =
Offset / 8;
5623 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5630 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5631 ValRegs.push_back(Dst);
5632 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5634 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5643 unsigned HandledOffset =
5644 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5648 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5651 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5652 LeftoverTy, NarrowLeftoverRegs);
5666 switch (
MI.getOpcode()) {
5667 case G_IMPLICIT_DEF:
5683 case G_FCANONICALIZE:
5700 case G_INTRINSIC_LRINT:
5701 case G_INTRINSIC_LLRINT:
5702 case G_INTRINSIC_ROUND:
5703 case G_INTRINSIC_ROUNDEVEN:
5706 case G_INTRINSIC_TRUNC:
5734 case G_FMINNUM_IEEE:
5735 case G_FMAXNUM_IEEE:
5757 case G_CTLZ_ZERO_POISON:
5759 case G_CTTZ_ZERO_POISON:
5776 case G_ADDRSPACE_CAST:
5789 case G_STRICT_FLDEXP:
5791 case G_TRUNC_SSAT_S:
5792 case G_TRUNC_SSAT_U:
5793 case G_TRUNC_USAT_U:
5801 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5806 case G_UNMERGE_VALUES:
5808 case G_BUILD_VECTOR:
5809 assert(TypeIdx == 0 &&
"not a vector type index");
5811 case G_CONCAT_VECTORS:
5815 case G_EXTRACT_VECTOR_ELT:
5816 case G_INSERT_VECTOR_ELT:
5825 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5826 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5828 case G_SHUFFLE_VECTOR:
5834 case G_INTRINSIC_FPTRUNC_ROUND:
5844 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5845 "Not a bitcast operation");
5850 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5852 unsigned NewElemCount =
5855 if (NewElemCount == 1) {
5858 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5865 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5874 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5875 MI.eraseFromParent();
5881 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5885 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5886 MI.getFirst3RegLLTs();
5889 if (DstTy != Src1Ty)
5891 if (DstTy != Src2Ty)
5906 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5922 unsigned InputUsed[2] = {-1U, -1U};
5923 unsigned FirstMaskIdx =
High * NewElts;
5924 bool UseBuildVector =
false;
5925 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5927 int Idx = Mask[FirstMaskIdx + MaskOffset];
5932 if (
Input >= std::size(Inputs)) {
5939 Idx -=
Input * NewElts;
5943 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5944 if (InputUsed[OpNo] ==
Input) {
5947 }
else if (InputUsed[OpNo] == -1U) {
5949 InputUsed[OpNo] =
Input;
5954 if (OpNo >= std::size(InputUsed)) {
5957 UseBuildVector =
true;
5962 Ops.push_back(Idx + OpNo * NewElts);
5965 if (UseBuildVector) {
5970 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5972 int Idx = Mask[FirstMaskIdx + MaskOffset];
5977 if (
Input >= std::size(Inputs)) {
5984 Idx -=
Input * NewElts;
5988 .buildExtractVectorElement(
5989 EltTy, Inputs[
Input],
5995 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5996 }
else if (InputUsed[0] == -1U) {
5998 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5999 }
else if (NewElts == 1) {
6000 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6002 Register Op0 = Inputs[InputUsed[0]];
6006 : Inputs[InputUsed[1]];
6008 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6015 MI.eraseFromParent();
6028 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6034 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6037 const unsigned NumParts =
6039 : SrcTy.getNumElements();
6043 if (DstTy != NarrowTy)
6049 unsigned NumPartsLeft = NumParts;
6050 while (NumPartsLeft > 1) {
6051 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6054 .buildInstr(ScalarOpc, {NarrowTy},
6055 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
6058 SplitSrcs = PartialResults;
6059 PartialResults.
clear();
6060 NumPartsLeft = SplitSrcs.
size();
6064 MI.eraseFromParent();
6069 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6070 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
6073 MI.eraseFromParent();
6077 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6079 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
6087 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6090 Register Acc = PartialReductions[0];
6091 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6092 if (Part == NumParts - 1) {
6094 {Acc, PartialReductions[Part]});
6097 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
6101 MI.eraseFromParent();
6107 unsigned int TypeIdx,
6109 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6110 MI.getFirst3RegLLTs();
6111 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6115 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6116 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6117 "Unexpected vecreduce opcode");
6118 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6119 ? TargetOpcode::G_FADD
6120 : TargetOpcode::G_FMUL;
6123 unsigned NumParts = SrcTy.getNumElements();
6126 for (
unsigned i = 0; i < NumParts; i++)
6127 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
6131 MI.eraseFromParent();
6138 unsigned ScalarOpc) {
6146 while (SplitSrcs.
size() > 1) {
6148 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6156 SplitSrcs = std::move(PartialRdxs);
6160 MI.getOperand(1).setReg(SplitSrcs[0]);
6167 const LLT HalfTy,
const LLT AmtTy) {
6169 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6170 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6174 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6175 MI.eraseFromParent();
6181 unsigned VTBits = 2 * NVTBits;
6184 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6185 if (Amt.
ugt(VTBits)) {
6187 }
else if (Amt.
ugt(NVTBits)) {
6190 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6191 }
else if (Amt == NVTBits) {
6199 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6202 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6203 if (Amt.
ugt(VTBits)) {
6205 }
else if (Amt.
ugt(NVTBits)) {
6207 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6209 }
else if (Amt == NVTBits) {
6213 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6215 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6217 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6223 if (Amt.
ugt(VTBits)) {
6225 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6226 }
else if (Amt.
ugt(NVTBits)) {
6228 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6230 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6231 }
else if (Amt == NVTBits) {
6234 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6236 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6238 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6240 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6247 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6248 MI.eraseFromParent();
6264 LLT DstTy = MRI.getType(DstReg);
6269 LLT ShiftAmtTy = MRI.getType(Amt);
6271 if (DstEltSize % 2 != 0)
6287 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6298 const unsigned NewBitSize = DstEltSize / 2;
6310 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6312 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6313 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6316 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6317 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6319 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6324 switch (
MI.getOpcode()) {
6325 case TargetOpcode::G_SHL: {
6327 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6329 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6330 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6331 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6334 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6335 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6337 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6339 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6341 ResultRegs[0] =
Lo.getReg(0);
6342 ResultRegs[1] =
Hi.getReg(0);
6345 case TargetOpcode::G_LSHR:
6346 case TargetOpcode::G_ASHR: {
6348 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6350 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6351 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6352 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6356 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6359 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6360 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6362 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6366 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6368 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6370 ResultRegs[0] =
Lo.getReg(0);
6371 ResultRegs[1] =
Hi.getReg(0);
6378 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6379 MI.eraseFromParent();
6388 LLT TargetTy,
LLT ShiftAmtTy) {
6391 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6393 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6394 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6395 const bool NeedsInterWordShift = ShiftBits != 0;
6398 case TargetOpcode::G_SHL: {
6401 if (PartIdx < ShiftWords)
6404 unsigned SrcIdx = PartIdx - ShiftWords;
6405 if (!NeedsInterWordShift)
6406 return SrcParts[SrcIdx];
6411 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6415 return Hi.getReg(0);
6418 case TargetOpcode::G_LSHR: {
6419 unsigned SrcIdx = PartIdx + ShiftWords;
6420 if (SrcIdx >= NumParts)
6422 if (!NeedsInterWordShift)
6423 return SrcParts[SrcIdx];
6427 if (SrcIdx + 1 < NumParts) {
6428 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6432 return Lo.getReg(0);
6435 case TargetOpcode::G_ASHR: {
6437 unsigned SrcIdx = PartIdx + ShiftWords;
6438 if (SrcIdx >= NumParts)
6440 if (!NeedsInterWordShift)
6441 return SrcParts[SrcIdx];
6446 (SrcIdx == NumParts - 1)
6450 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6472 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6473 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6478 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6487 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6488 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6490 auto IsZeroBitShift =
6498 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6499 : TargetOpcode::G_SHL;
6502 auto TargetBitsConst =
6504 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6509 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6514 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6516 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6520 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6533 LLT DstTy = MRI.getType(DstReg);
6537 const unsigned NumParts = DstBits / TargetBits;
6539 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6549 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6550 MI.eraseFromParent();
6555 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6556 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6562 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6566 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6569 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6570 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6574 for (
unsigned I = 0;
I < NumParts; ++
I)
6576 Params, TargetTy, ShiftAmtTy);
6578 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6579 MI.eraseFromParent();
6588 LLT DstTy = MRI.getType(DstReg);
6589 LLT ShiftAmtTy = MRI.getType(AmtReg);
6593 const unsigned NumParts = DstBits / TargetBits;
6595 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6612 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6624 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6625 auto TargetBitsLog2Const =
6626 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6627 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6630 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6632 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6640 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6641 auto TargetBitsMinusOneConst =
6642 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6644 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6645 TargetBitsMinusOneConst)
6648 FillValue = ZeroReg;
6656 for (
unsigned I = 0;
I < NumParts; ++
I) {
6658 Register InBoundsResult = FillValue;
6668 for (
unsigned K = 0; K < NumParts; ++K) {
6669 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6671 WordShift, WordShiftKConst);
6683 switch (
MI.getOpcode()) {
6684 case TargetOpcode::G_SHL:
6685 MainSrcIdx = (int)
I - (
int)K;
6686 CarrySrcIdx = MainSrcIdx - 1;
6688 case TargetOpcode::G_LSHR:
6689 case TargetOpcode::G_ASHR:
6690 MainSrcIdx = (int)
I + (
int)K;
6691 CarrySrcIdx = MainSrcIdx + 1;
6699 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6700 Register MainOp = SrcParts[MainSrcIdx];
6704 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6705 CarryOp = SrcParts[CarrySrcIdx];
6706 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6707 CarrySrcIdx >= (
int)NumParts)
6708 CarryOp = FillValue;
6714 ResultForK = FillValue;
6720 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6727 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6731 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6732 MI.eraseFromParent();
6739 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6742 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6757 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6762 "getNeutralElementForVecReduce called with invalid opcode!");
6763 case TargetOpcode::G_VECREDUCE_ADD:
6764 case TargetOpcode::G_VECREDUCE_OR:
6765 case TargetOpcode::G_VECREDUCE_XOR:
6766 case TargetOpcode::G_VECREDUCE_UMAX:
6768 case TargetOpcode::G_VECREDUCE_MUL:
6770 case TargetOpcode::G_VECREDUCE_AND:
6771 case TargetOpcode::G_VECREDUCE_UMIN:
6774 case TargetOpcode::G_VECREDUCE_SMAX:
6777 case TargetOpcode::G_VECREDUCE_SMIN:
6780 case TargetOpcode::G_VECREDUCE_FADD:
6782 case TargetOpcode::G_VECREDUCE_FMUL:
6784 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6785 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6786 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6787 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6795 unsigned Opc =
MI.getOpcode();
6797 case TargetOpcode::G_IMPLICIT_DEF:
6798 case TargetOpcode::G_LOAD: {
6806 case TargetOpcode::G_STORE:
6813 case TargetOpcode::G_AND:
6814 case TargetOpcode::G_OR:
6815 case TargetOpcode::G_XOR:
6816 case TargetOpcode::G_ADD:
6817 case TargetOpcode::G_SUB:
6818 case TargetOpcode::G_MUL:
6819 case TargetOpcode::G_FADD:
6820 case TargetOpcode::G_FSUB:
6821 case TargetOpcode::G_FMUL:
6822 case TargetOpcode::G_FDIV:
6823 case TargetOpcode::G_FCOPYSIGN:
6824 case TargetOpcode::G_UADDSAT:
6825 case TargetOpcode::G_USUBSAT:
6826 case TargetOpcode::G_SADDSAT:
6827 case TargetOpcode::G_SSUBSAT:
6828 case TargetOpcode::G_SMIN:
6829 case TargetOpcode::G_SMAX:
6830 case TargetOpcode::G_UMIN:
6831 case TargetOpcode::G_UMAX:
6832 case TargetOpcode::G_FMINNUM:
6833 case TargetOpcode::G_FMAXNUM:
6834 case TargetOpcode::G_FMINNUM_IEEE:
6835 case TargetOpcode::G_FMAXNUM_IEEE:
6836 case TargetOpcode::G_FMINIMUM:
6837 case TargetOpcode::G_FMAXIMUM:
6838 case TargetOpcode::G_FMINIMUMNUM:
6839 case TargetOpcode::G_FMAXIMUMNUM:
6840 case TargetOpcode::G_STRICT_FADD:
6841 case TargetOpcode::G_STRICT_FSUB:
6842 case TargetOpcode::G_STRICT_FMUL: {
6850 case TargetOpcode::G_SHL:
6851 case TargetOpcode::G_ASHR:
6852 case TargetOpcode::G_LSHR: {
6858 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6864 case TargetOpcode::G_FMA:
6865 case TargetOpcode::G_STRICT_FMA:
6866 case TargetOpcode::G_FSHR:
6867 case TargetOpcode::G_FSHL: {
6876 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6877 case TargetOpcode::G_EXTRACT:
6884 case TargetOpcode::G_INSERT:
6885 case TargetOpcode::G_INSERT_VECTOR_ELT:
6886 case TargetOpcode::G_FREEZE:
6887 case TargetOpcode::G_FNEG:
6888 case TargetOpcode::G_FABS:
6889 case TargetOpcode::G_FSQRT:
6890 case TargetOpcode::G_FCEIL:
6891 case TargetOpcode::G_FFLOOR:
6892 case TargetOpcode::G_FNEARBYINT:
6893 case TargetOpcode::G_FRINT:
6894 case TargetOpcode::G_INTRINSIC_ROUND:
6895 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6896 case TargetOpcode::G_INTRINSIC_TRUNC:
6897 case TargetOpcode::G_BITREVERSE:
6898 case TargetOpcode::G_BSWAP:
6899 case TargetOpcode::G_FCANONICALIZE:
6900 case TargetOpcode::G_SEXT_INREG:
6901 case TargetOpcode::G_ABS:
6902 case TargetOpcode::G_CTLZ:
6903 case TargetOpcode::G_CTPOP:
6911 case TargetOpcode::G_SELECT: {
6912 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6914 if (!CondTy.isScalar() ||
6920 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6922 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6927 if (CondTy.isVector())
6937 case TargetOpcode::G_UNMERGE_VALUES:
6939 case TargetOpcode::G_PHI:
6941 case TargetOpcode::G_SHUFFLE_VECTOR:
6943 case TargetOpcode::G_BUILD_VECTOR: {
6945 for (
auto Op :
MI.uses()) {
6953 MIRBuilder.buildDeleteTrailingVectorElements(
6954 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6955 MI.eraseFromParent();
6958 case TargetOpcode::G_SEXT:
6959 case TargetOpcode::G_ZEXT:
6960 case TargetOpcode::G_ANYEXT:
6961 case TargetOpcode::G_TRUNC:
6962 case TargetOpcode::G_FPTRUNC:
6963 case TargetOpcode::G_FPEXT:
6964 case TargetOpcode::G_FPTOSI:
6965 case TargetOpcode::G_FPTOUI:
6966 case TargetOpcode::G_FPTOSI_SAT:
6967 case TargetOpcode::G_FPTOUI_SAT:
6968 case TargetOpcode::G_SITOFP:
6969 case TargetOpcode::G_UITOFP: {
6976 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6979 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6987 case TargetOpcode::G_ICMP:
6988 case TargetOpcode::G_FCMP: {
6996 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7001 case TargetOpcode::G_BITCAST: {
7005 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7006 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7022 case TargetOpcode::G_VECREDUCE_FADD:
7023 case TargetOpcode::G_VECREDUCE_FMUL:
7024 case TargetOpcode::G_VECREDUCE_ADD:
7025 case TargetOpcode::G_VECREDUCE_MUL:
7026 case TargetOpcode::G_VECREDUCE_AND:
7027 case TargetOpcode::G_VECREDUCE_OR:
7028 case TargetOpcode::G_VECREDUCE_XOR:
7029 case TargetOpcode::G_VECREDUCE_SMAX:
7030 case TargetOpcode::G_VECREDUCE_SMIN:
7031 case TargetOpcode::G_VECREDUCE_UMAX:
7032 case TargetOpcode::G_VECREDUCE_UMIN: {
7033 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7035 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7036 auto NeutralElement = getNeutralElementForVecReduce(
7042 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7043 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7044 NeutralElement, Idx);
7048 MO.
setReg(NewVec.getReg(0));
7060 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7062 unsigned MaskNumElts = Mask.size();
7063 unsigned SrcNumElts = SrcTy.getNumElements();
7066 if (MaskNumElts == SrcNumElts)
7069 if (MaskNumElts < SrcNumElts) {
7077 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7078 MI.getOperand(1).getReg(),
7079 MI.getOperand(2).getReg(), NewMask);
7080 MI.eraseFromParent();
7085 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7086 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7095 MOps1[0] =
MI.getOperand(1).getReg();
7096 MOps2[0] =
MI.getOperand(2).getReg();
7098 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7099 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7103 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7105 if (Idx >=
static_cast<int>(SrcNumElts))
7106 Idx += PaddedMaskNumElts - SrcNumElts;
7111 if (MaskNumElts != PaddedMaskNumElts) {
7113 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7116 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7118 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7123 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7126 MI.eraseFromParent();
7132 unsigned int TypeIdx,
LLT MoreTy) {
7133 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7135 unsigned NumElts = DstTy.getNumElements();
7138 if (DstTy.isVector() && Src1Ty.isVector() &&
7139 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7147 if (DstTy != Src1Ty || DstTy != Src2Ty)
7155 for (
unsigned I = 0;
I != NumElts; ++
I) {
7157 if (Idx <
static_cast<int>(NumElts))
7160 NewMask[
I] = Idx - NumElts + WidenNumElts;
7164 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7165 MI.getOperand(1).getReg(),
7166 MI.getOperand(2).getReg(), NewMask);
7167 MI.eraseFromParent();
7176 unsigned SrcParts = Src1Regs.
size();
7177 unsigned DstParts = DstRegs.
size();
7179 unsigned DstIdx = 0;
7181 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7182 DstRegs[DstIdx] = FactorSum;
7187 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7189 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7190 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7192 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7198 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7199 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7200 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7201 unsigned i = RevI - 1;
7203 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7213 if (DstIdx != DstParts - 1) {
7214 MachineInstrBuilder Uaddo =
7215 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7216 FactorSum = Uaddo.
getReg(0);
7217 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7218 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7219 MachineInstrBuilder Uaddo =
7220 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7221 FactorSum = Uaddo.
getReg(0);
7222 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7223 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7227 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7228 for (
unsigned i = 2; i < Factors.
size(); ++i)
7229 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7232 CarrySumPrevDstIdx = CarrySum;
7233 DstRegs[DstIdx] = FactorSum;
7245 LLT DstType = MRI.getType(DstReg);
7247 if (DstType.isVector())
7250 unsigned Opcode =
MI.getOpcode();
7251 unsigned OpO, OpE, OpF;
7253 case TargetOpcode::G_SADDO:
7254 case TargetOpcode::G_SADDE:
7255 case TargetOpcode::G_UADDO:
7256 case TargetOpcode::G_UADDE:
7257 case TargetOpcode::G_ADD:
7258 OpO = TargetOpcode::G_UADDO;
7259 OpE = TargetOpcode::G_UADDE;
7260 OpF = TargetOpcode::G_UADDE;
7261 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7262 OpF = TargetOpcode::G_SADDE;
7264 case TargetOpcode::G_SSUBO:
7265 case TargetOpcode::G_SSUBE:
7266 case TargetOpcode::G_USUBO:
7267 case TargetOpcode::G_USUBE:
7268 case TargetOpcode::G_SUB:
7269 OpO = TargetOpcode::G_USUBO;
7270 OpE = TargetOpcode::G_USUBE;
7271 OpF = TargetOpcode::G_USUBE;
7272 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7273 OpF = TargetOpcode::G_SSUBE;
7280 unsigned NumDefs =
MI.getNumExplicitDefs();
7281 Register Src1 =
MI.getOperand(NumDefs).getReg();
7282 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7285 CarryDst =
MI.getOperand(1).getReg();
7286 if (
MI.getNumOperands() == NumDefs + 3)
7287 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7289 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7290 LLT LeftoverTy, DummyTy;
7292 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7297 int NarrowParts = Src1Regs.
size();
7298 Src1Regs.
append(Src1Left);
7299 Src2Regs.
append(Src2Left);
7302 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7304 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7307 if (i == e - 1 && CarryDst)
7308 CarryOut = CarryDst;
7310 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7313 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7314 {Src1Regs[i], Src2Regs[i]});
7315 }
else if (i == e - 1) {
7316 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7317 {Src1Regs[i], Src2Regs[i], CarryIn});
7319 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7320 {Src1Regs[i], Src2Regs[i], CarryIn});
7326 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7327 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7328 ArrayRef(DstRegs).drop_front(NarrowParts));
7330 MI.eraseFromParent();
7336 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7338 LLT Ty = MRI.getType(DstReg);
7342 unsigned Size = Ty.getSizeInBits();
7344 if (
Size % NarrowSize != 0)
7347 unsigned NumParts =
Size / NarrowSize;
7348 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7349 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7355 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7359 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7360 MI.eraseFromParent();
7370 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7373 LLT SrcTy = MRI.getType(Src);
7384 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7397 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7400 if (SizeOp1 % NarrowSize != 0)
7402 int NumParts = SizeOp1 / NarrowSize;
7405 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7409 uint64_t OpStart =
MI.getOperand(2).getImm();
7410 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7411 for (
int i = 0; i < NumParts; ++i) {
7412 unsigned SrcStart = i * NarrowSize;
7414 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7417 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7425 int64_t ExtractOffset;
7427 if (OpStart < SrcStart) {
7429 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7431 ExtractOffset = OpStart - SrcStart;
7432 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7436 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7438 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7439 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7446 if (MRI.getType(DstReg).isVector())
7447 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7448 else if (DstRegs.
size() > 1)
7449 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7452 MI.eraseFromParent();
7464 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7466 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7469 SrcRegs.
append(LeftoverRegs);
7473 uint64_t OpStart =
MI.getOperand(3).getImm();
7474 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7475 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7476 unsigned DstStart =
I * NarrowSize;
7478 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7486 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7488 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7492 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7500 int64_t ExtractOffset, InsertOffset;
7502 if (OpStart < DstStart) {
7504 ExtractOffset = DstStart - OpStart;
7505 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7507 InsertOffset = OpStart - DstStart;
7510 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7514 if (ExtractOffset != 0 || SegSize != OpSize) {
7516 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7517 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7520 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7521 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7529 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7532 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7534 MI.eraseFromParent();
7542 LLT DstTy = MRI.getType(DstReg);
7544 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7550 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7551 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7555 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7556 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7559 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7560 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7561 {Src0Regs[I], Src1Regs[I]});
7565 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7568 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7569 DstLeftoverRegs.
push_back(Inst.getReg(0));
7572 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7573 LeftoverTy, DstLeftoverRegs);
7575 MI.eraseFromParent();
7585 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7587 LLT DstTy = MRI.getType(DstReg);
7592 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7593 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7594 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7596 MI.eraseFromParent();
7606 Register CondReg =
MI.getOperand(1).getReg();
7607 LLT CondTy = MRI.getType(CondReg);
7608 if (CondTy.isVector())
7612 LLT DstTy = MRI.getType(DstReg);
7618 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7619 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7623 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7624 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7627 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7629 CondReg, Src1Regs[
I], Src2Regs[
I]);
7633 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7635 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7639 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7640 LeftoverTy, DstLeftoverRegs);
7642 MI.eraseFromParent();
7652 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7655 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7656 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7659 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7661 auto C_0 =
B.buildConstant(NarrowTy, 0);
7663 UnmergeSrc.getReg(1), C_0);
7664 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7665 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7666 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7667 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7668 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7669 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7671 MI.eraseFromParent();
7684 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7687 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7688 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7691 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7693 auto C_0 =
B.buildConstant(NarrowTy, 0);
7695 UnmergeSrc.getReg(0), C_0);
7696 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7697 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7698 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7699 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7700 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7701 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7703 MI.eraseFromParent();
7716 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7719 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7724 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7728 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7729 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7737 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7738 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7741 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7742 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7744 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7746 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7748 MI.eraseFromParent();
7758 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7761 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7762 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7764 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7765 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7766 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7768 MI.eraseFromParent();
7783 LLT ExpTy = MRI.getType(ExpReg);
7788 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7789 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7790 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7791 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7793 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7795 MI.getOperand(2).setReg(Trunc.getReg(0));
7802 unsigned Opc =
MI.getOpcode();
7805 auto QAction = LI.getAction(Q).Action;
7811 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7814 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7818 case TargetOpcode::G_CTLZ: {
7819 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7820 unsigned Len = SrcTy.getScalarSizeInBits();
7822 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7824 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7825 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7828 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7829 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7830 MI.eraseFromParent();
7846 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7847 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7850 Op = MIBOp.getReg(0);
7855 MI.eraseFromParent();
7858 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7861 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7865 case TargetOpcode::G_CTTZ: {
7866 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7868 unsigned Len = SrcTy.getScalarSizeInBits();
7869 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
7872 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
7873 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7876 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7877 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7878 MI.eraseFromParent();
7885 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7886 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7888 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7889 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7890 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7891 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7894 MI.eraseFromParent();
7898 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7899 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7903 case TargetOpcode::G_CTPOP: {
7905 LLT Ty = MRI.getType(SrcReg);
7906 unsigned Size = Ty.getScalarSizeInBits();
7918 auto C_1 =
B.buildConstant(Ty, 1);
7919 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7921 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7922 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7923 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7927 auto C_2 =
B.buildConstant(Ty, 2);
7928 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7930 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7931 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7932 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7933 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7940 auto C_4 =
B.buildConstant(Ty, 4);
7941 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7942 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7944 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7945 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7947 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
7950 if (
Size == 16 && !Ty.isVector()) {
7952 auto C_8 =
B.buildConstant(Ty, 8);
7953 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
7954 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
7955 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
7956 MI.eraseFromParent();
7965 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7967 auto IsMulSupported = [
this](
const LLT Ty) {
7968 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7971 if (IsMulSupported(Ty)) {
7972 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7973 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7975 auto ResTmp = B8Count;
7976 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7977 auto ShiftC =
B.buildConstant(Ty, Shift);
7978 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7979 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7981 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7983 MI.eraseFromParent();
7986 case TargetOpcode::G_CTLS: {
7987 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7991 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
7992 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
7994 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8000 MI.eraseFromParent();
8021 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8022 LLT Ty = MRI.getType(Dst);
8023 LLT ShTy = MRI.getType(Z);
8030 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8031 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8036 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8037 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8041 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8054 MI.eraseFromParent();
8060 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8061 LLT Ty = MRI.getType(Dst);
8062 LLT ShTy = MRI.getType(Z);
8065 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8075 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8076 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8077 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8078 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8079 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8083 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8086 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8089 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8091 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8092 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8093 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8096 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8098 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8100 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8103 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8104 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8109 MI.eraseFromParent();
8120 LLT Ty = MRI.getType(Dst);
8121 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8123 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8124 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8127 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8128 return lowerFunnelShiftAsShifts(
MI);
8132 if (Result == UnableToLegalize)
8133 return lowerFunnelShiftAsShifts(
MI);
8138 auto [Dst, Src] =
MI.getFirst2Regs();
8139 LLT DstTy = MRI.getType(Dst);
8140 LLT SrcTy = MRI.getType(Src);
8144 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8152 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8156 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8160 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8165 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8166 {UnmergeSrc.getReg(0)});
8167 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8168 {UnmergeSrc.getReg(1)});
8171 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8173 MI.eraseFromParent();
8190 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8194 LLT DstTy = MRI.getType(DstReg);
8195 LLT SrcTy = MRI.getType(SrcReg);
8203 SrcTy.getElementCount().divideCoefficientBy(2));
8216 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8228 MI.eraseFromParent();
8237 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8238 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8239 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8240 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8241 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8242 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8243 MI.eraseFromParent();
8248 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8250 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8251 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8256 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8257 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8259 return lowerRotateWithReverseRotate(
MI);
8262 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8263 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8264 bool IsFShLegal =
false;
8265 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8266 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8270 MI.eraseFromParent();
8275 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8278 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8283 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8284 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8285 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8291 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8292 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8294 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8300 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8301 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8303 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8305 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8310 MI.eraseFromParent();
8318 auto [Dst, Src] =
MI.getFirst2Regs();
8323 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8351 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8364 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8368 MI.eraseFromParent();
8376 auto [Dst, Src] =
MI.getFirst2Regs();
8381 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8394 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8396 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8401 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8403 MI.eraseFromParent();
8411 auto [Dst, Src] =
MI.getFirst2Regs();
8415 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8426 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8427 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8429 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8436 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8437 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8438 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8440 MI.eraseFromParent();
8451 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8452 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8458 MI.eraseFromParent();
8463 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8466 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8467 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8468 MIRBuilder.buildSelect(Dst, Src, True, False);
8469 MI.eraseFromParent();
8473 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8493 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8500 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8501 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8502 MIRBuilder.buildSelect(Dst, Src, True, False);
8503 MI.eraseFromParent();
8507 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8513 if (DstTy.getScalarSizeInBits() == 32) {
8520 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8521 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8523 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8530 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8531 MI.eraseFromParent();
8539 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8543 if (SrcTy !=
S64 && SrcTy !=
S32)
8545 if (DstTy !=
S32 && DstTy !=
S64)
8572 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8574 MI.eraseFromParent();
8579 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8584 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8591 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8593 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8594 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8596 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8597 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8599 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8601 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8602 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8603 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8606 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8607 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8608 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8610 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8613 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8618 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8619 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8625 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8627 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8628 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8630 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8635 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8636 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8638 MI.eraseFromParent();
8644 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8646 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8647 unsigned SatWidth = DstTy.getScalarSizeInBits();
8651 APInt MinInt, MaxInt;
8674 if (AreExactFloatBounds) {
8676 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8679 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8681 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8690 MI.eraseFromParent();
8695 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8700 MI.eraseFromParent();
8707 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8715 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8725 MI.eraseFromParent();
8731 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8735 MI.eraseFromParent();
8742 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8743 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8744 "Only G_FPEXT and G_FPTRUNC are expected");
8746 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8751 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8753 StoreOpc = TargetOpcode::G_STORE;
8754 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8757 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8758 LoadOpc = TargetOpcode::G_LOAD;
8767 StackTy, StackTyAlign);
8768 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8771 StackTy, StackTyAlign);
8772 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8774 MI.eraseFromParent();
8784 auto [Dst, Src] =
MI.getFirst2Regs();
8788 if (MRI.getType(Src).isVector())
8792 unsigned Flags =
MI.getFlags();
8795 MI.eraseFromParent();
8799 const unsigned ExpMask = 0x7ff;
8800 const unsigned ExpBiasf64 = 1023;
8801 const unsigned ExpBiasf16 = 15;
8830 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8890 MI.eraseFromParent();
8897 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8905 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
8931 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
8933 MI.eraseFromParent();
8939 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8940 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
8943 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
8950 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8951 LLT Ty = MRI.getType(Dst);
8953 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8954 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8955 MI.eraseFromParent();
8960 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
8961 LLT Ty = MRI.getType(Src);
8962 auto Flags =
MI.getFlags();
8970 FracToUse = FracPart.getReg(0);
8972 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
8976 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8978 FracToUse =
Select.getReg(0);
8981 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
8984 MI.eraseFromParent();
8990 case TargetOpcode::G_SMIN:
8992 case TargetOpcode::G_SMAX:
8994 case TargetOpcode::G_UMIN:
8996 case TargetOpcode::G_UMAX:
9004 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9009 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9010 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9012 MI.eraseFromParent();
9021 LLT DstTy = MRI.getType(Dst);
9022 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9032 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9033 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9035 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9038 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9039 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9040 if (TLI.preferSelectsOverBooleanArithmetic(
9043 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9044 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9046 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9047 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9053 unsigned BoolExtOp =
9055 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9056 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9060 MI.eraseFromParent();
9066 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9067 const int Src0Size = Src0Ty.getScalarSizeInBits();
9068 const int Src1Size = Src1Ty.getScalarSizeInBits();
9078 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9079 Src0Ty.getScalarType().isInteger()))
9080 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9082 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9083 Src1Ty.getScalarType().isInteger()))
9084 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9089 auto NotSignBitMask =
MIRBuilder.buildConstant(
9093 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9095 if (Src0Ty == Src1Ty) {
9096 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9097 }
else if (Src0Size > Src1Size) {
9098 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9099 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9100 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9101 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
9103 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9104 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9105 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9106 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9112 unsigned Flags =
MI.getFlags();
9117 if (DstTy == DstIntTy)
9118 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9124 MI.eraseFromParent();
9135 switch (
MI.getOpcode()) {
9136 case TargetOpcode::G_FMINNUM:
9137 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9139 case TargetOpcode::G_FMINIMUMNUM:
9140 NewOp = TargetOpcode::G_FMINNUM;
9142 case TargetOpcode::G_FMAXNUM:
9143 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9145 case TargetOpcode::G_FMAXIMUMNUM:
9146 NewOp = TargetOpcode::G_FMAXNUM;
9152 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9153 LLT Ty = MRI.getType(Dst);
9162 if (!VT->isKnownNeverSNaN(Src0))
9163 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9165 if (!VT->isKnownNeverSNaN(Src1))
9166 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9171 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9172 MI.eraseFromParent();
9178 unsigned Opc =
MI.getOpcode();
9179 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9180 LLT Ty = MRI.getType(Dst);
9183 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9185 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9186 unsigned OpcNonIeee =
9187 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9188 bool MinMaxMustRespectOrderedZero =
false;
9192 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9194 MinMaxMustRespectOrderedZero =
true;
9195 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9200 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9205 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9208 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9212 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9214 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9224 const unsigned Flags =
MI.getFlags();
9230 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9232 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9234 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9236 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9238 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9243 MI.eraseFromParent();
9250 LLT Ty = MRI.getType(DstReg);
9251 unsigned Flags =
MI.getFlags();
9256 MI.eraseFromParent();
9262 auto [DstReg,
X] =
MI.getFirst2Regs();
9263 const unsigned Flags =
MI.getFlags();
9264 const LLT Ty = MRI.getType(DstReg);
9276 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9278 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9283 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9284 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9285 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9286 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9288 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9290 MI.eraseFromParent();
9295 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9296 unsigned Flags =
MI.getFlags();
9297 LLT Ty = MRI.getType(DstReg);
9304 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9305 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9308 SrcReg, Zero, Flags);
9310 SrcReg, Trunc, Flags);
9314 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9315 MI.eraseFromParent();
9321 const unsigned NumOps =
MI.getNumOperands();
9322 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9323 unsigned PartSize = Src0Ty.getSizeInBits();
9328 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9329 const unsigned Offset = (
I - 1) * PartSize;
9332 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9335 MRI.createGenericVirtualRegister(WideTy);
9338 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9339 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9340 ResultReg = NextResult;
9343 if (DstTy.isPointer()) {
9344 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9345 DstTy.getAddressSpace())) {
9353 MI.eraseFromParent();
9359 const unsigned NumDst =
MI.getNumOperands() - 1;
9360 Register SrcReg =
MI.getOperand(NumDst).getReg();
9361 Register Dst0Reg =
MI.getOperand(0).getReg();
9362 LLT DstTy = MRI.getType(Dst0Reg);
9371 LLT IntTy = MRI.getType(SrcReg);
9376 unsigned Offset = DstSize;
9377 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9379 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9383 MI.eraseFromParent();
9402 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9403 InsertVal =
MI.getOperand(2).getReg();
9405 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9407 LLT VecTy = MRI.getType(SrcVec);
9417 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9418 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9420 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9423 MI.eraseFromParent();
9428 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9439 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9446 int64_t
Offset = IdxVal * EltBytes;
9457 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9460 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9462 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9465 MI.eraseFromParent();
9471 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9472 MI.getFirst3RegLLTs();
9482 for (
int Idx : Mask) {
9484 if (!
Undef.isValid())
9490 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9492 int NumElts = Src0Ty.getNumElements();
9493 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9494 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9495 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9497 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9499 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9504 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9505 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9506 MI.eraseFromParent();
9512 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9513 MI.getFirst4RegLLTs();
9515 if (VecTy.isScalableVector())
9531 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9534 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9537 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9540 std::optional<APInt> PassthruSplatVal =
9543 if (PassthruSplatVal.has_value()) {
9545 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9546 }
else if (HasPassthru) {
9547 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9548 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9554 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9558 unsigned NumElmts = VecTy.getNumElements();
9559 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9561 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9564 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9567 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9572 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9574 if (HasPassthru &&
I == NumElmts - 1) {
9577 auto AllLanesSelected =
MIRBuilder.buildICmp(
9579 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9580 {OutPos, EndOfVector});
9584 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9586 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9591 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9593 MI.eraseFromParent();
9610 if (Alignment >
Align(1)) {
9622 const auto &MF = *
MI.getMF();
9628 Register AllocSize =
MI.getOperand(1).getReg();
9631 LLT PtrTy = MRI.getType(Dst);
9632 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9639 MI.eraseFromParent();
9645 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9650 MI.eraseFromParent();
9656 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9661 MI.eraseFromParent();
9667 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9668 unsigned Offset =
MI.getOperand(2).getImm();
9671 if (SrcTy.isVector()) {
9672 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9673 unsigned DstSize = DstTy.getSizeInBits();
9675 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9676 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9678 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9682 for (
unsigned Idx =
Offset / SrcEltSize;
9683 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9684 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9686 if (SubVectorElts.
size() == 1)
9687 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9689 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9691 MI.eraseFromParent();
9697 if ((SrcTy.isPointer() &&
9698 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9699 (DstTy.isPointer() &&
9700 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9701 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9705 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9706 (SrcTy.isScalar() || SrcTy.isPointer() ||
9707 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9708 LLT SrcIntTy = SrcTy;
9709 if (!SrcTy.isScalar()) {
9711 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9715 if (DstTy.isPointer())
9717 MRI.createGenericVirtualRegister(
LLT::scalar(DstTy.getSizeInBits()));
9723 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9727 if (DstTy.isPointer())
9730 MI.eraseFromParent();
9738 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9741 LLT DstTy = MRI.getType(Src);
9742 LLT InsertTy = MRI.getType(InsertSrc);
9745 bool IsNonIntegralInsert =
9755 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9756 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9763 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9765 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9769 for (; Idx <
Offset / EltSize; ++Idx) {
9770 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9775 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9776 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9778 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9782 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
9784 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
9791 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9794 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9795 MI.eraseFromParent();
9804 if (IsNonIntegralDst || IsNonIntegralInsert) {
9805 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9809 LLT IntDstTy = DstTy;
9813 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9818 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9824 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9830 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9831 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9832 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9835 MI.eraseFromParent();
9841 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9842 MI.getFirst4RegLLTs();
9843 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9846 LLT BoolTy = Dst1Ty;
9848 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9863 auto ResultLowerThanLHS =
9867 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
9871 auto LHSLessThanRHS =
9873 auto ResultNegative =
9875 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
9879 MI.eraseFromParent();
9885 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9886 const LLT Ty = MRI.getType(Res);
9889 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9890 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9891 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9902 MI.eraseFromParent();
9907 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9908 const LLT Ty = MRI.getType(Res);
9911 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9912 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9913 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9918 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9923 MI.eraseFromParent();
9929 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9930 LLT Ty = MRI.getType(Res);
9934 switch (
MI.getOpcode()) {
9937 case TargetOpcode::G_UADDSAT:
9940 BaseOp = TargetOpcode::G_ADD;
9942 case TargetOpcode::G_SADDSAT:
9945 BaseOp = TargetOpcode::G_ADD;
9947 case TargetOpcode::G_USUBSAT:
9950 BaseOp = TargetOpcode::G_SUB;
9952 case TargetOpcode::G_SSUBSAT:
9955 BaseOp = TargetOpcode::G_SUB;
9970 uint64_t NumBits = Ty.getScalarSizeInBits();
9981 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9989 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9994 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9995 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9998 MI.eraseFromParent();
10004 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10005 LLT Ty = MRI.getType(Res);
10009 unsigned OverflowOp;
10010 switch (
MI.getOpcode()) {
10013 case TargetOpcode::G_UADDSAT:
10016 OverflowOp = TargetOpcode::G_UADDO;
10018 case TargetOpcode::G_SADDSAT:
10021 OverflowOp = TargetOpcode::G_SADDO;
10023 case TargetOpcode::G_USUBSAT:
10026 OverflowOp = TargetOpcode::G_USUBO;
10028 case TargetOpcode::G_SSUBSAT:
10031 OverflowOp = TargetOpcode::G_SSUBO;
10036 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10037 Register Tmp = OverflowRes.getReg(0);
10038 Register Ov = OverflowRes.getReg(1);
10047 uint64_t NumBits = Ty.getScalarSizeInBits();
10048 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10049 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10052 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10060 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10062 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10064 MI.eraseFromParent();
10070 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10071 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10072 "Expected shlsat opcode!");
10073 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10074 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10075 LLT Ty = MRI.getType(Res);
10079 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10080 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10089 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10094 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10096 MI.eraseFromParent();
10101 auto [Dst, Src] =
MI.getFirst2Regs();
10102 const LLT Ty = MRI.getType(Src);
10103 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10104 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10107 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10108 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10109 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10110 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10113 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10116 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10117 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10119 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10120 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10121 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10123 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10124 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10125 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10127 Res.getInstr()->getOperand(0).setReg(Dst);
10129 MI.eraseFromParent();
10136 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10139 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10140 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10141 return B.buildOr(Dst,
LHS,
RHS);
10146 auto [Dst, Src] =
MI.getFirst2Regs();
10147 const LLT SrcTy = MRI.getType(Src);
10148 unsigned Size = SrcTy.getScalarSizeInBits();
10149 unsigned VSize = SrcTy.getSizeInBits();
10152 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10153 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10154 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10155 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10160 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10161 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10162 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10166 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10189 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10193 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10196 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10200 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10204 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10209 MI.eraseFromParent();
10217 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10218 int NameOpIdx = IsRead ? 1 : 0;
10219 int ValRegIndex = IsRead ? 0 : 1;
10221 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10222 const LLT Ty = MRI.getType(ValReg);
10224 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10231 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10232 Fn,
MI.getDebugLoc()));
10236 MI.eraseFromParent();
10245 MI.eraseFromParent();
10251 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10252 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10253 Register Result =
MI.getOperand(0).getReg();
10254 LLT OrigTy = MRI.getType(Result);
10258 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10259 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10261 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10263 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10264 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10267 MI.eraseFromParent();
10273 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10278 MI.eraseFromParent();
10283 MI.eraseFromParent();
10290 unsigned BitSize = SrcTy.getScalarSizeInBits();
10294 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10301 APInt ExpMask = Inf;
10303 APInt QNaNBitMask =
10307 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10308 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10309 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10310 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10311 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10313 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10317 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10319 LLT DstTyCopy = DstTy;
10321 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10349 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10352 Mask &= ~PartialCheck;
10361 else if (PartialCheck ==
fcZero)
10373 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10374 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10375 auto SubnormalRes =
10377 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10379 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10380 appendToRes(SubnormalRes);
10387 else if (PartialCheck ==
fcInf)
10392 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10399 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10400 if (PartialCheck ==
fcNan) {
10404 }
else if (PartialCheck ==
fcQNan) {
10414 Abs, InfWithQnanBitC);
10415 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10422 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10424 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10425 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10428 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10430 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10433 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10434 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10436 appendToRes(NormalRes);
10440 MI.eraseFromParent();
10446 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10447 MI.getFirst4RegLLTs();
10456 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10457 Op1Ty = MRI.getType(Op1Reg);
10458 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10459 Op2Ty = MRI.getType(Op2Reg);
10463 if (MaskTy.isScalar()) {
10471 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10474 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10476 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10478 if (DstTy.isVector()) {
10480 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10481 MaskReg = ShufSplat.getReg(0);
10485 }
else if (!DstTy.isVector()) {
10490 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10494 if (!Op1Ty.getScalarType().isAnyScalar() &&
10495 !Op1Ty.getScalarType().isInteger())
10496 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10498 if (!Op2Ty.getScalarType().isAnyScalar() &&
10499 !Op2Ty.getScalarType().isInteger()) {
10501 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10502 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10505 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10506 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10507 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10512 if (DstTy == Op1TyInt)
10515 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10519 MI.eraseFromParent();
10525 unsigned Opcode =
MI.getOpcode();
10528 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10529 : TargetOpcode::G_UDIV,
10530 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10532 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10533 : TargetOpcode::G_UREM,
10534 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10535 MI.eraseFromParent();
10545 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10549 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10552 MI.eraseFromParent();
10562 Register SrcReg =
MI.getOperand(1).getReg();
10563 LLT Ty = MRI.getType(SrcReg);
10564 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10567 MI.eraseFromParent();
10573 Register SrcReg =
MI.getOperand(1).getReg();
10574 Register DestReg =
MI.getOperand(0).getReg();
10576 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10577 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10580 MI.eraseFromParent();
10586 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10587 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10588 "Expected G_ABDS or G_ABDU instruction");
10590 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10591 LLT Ty = MRI.getType(LHS);
10601 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10603 MI.eraseFromParent();
10609 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10610 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10611 "Expected G_ABDS or G_ABDU instruction");
10613 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10614 LLT Ty = MRI.getType(LHS);
10619 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10620 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10621 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10623 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10624 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10626 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10628 MI.eraseFromParent();
10633 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10638 if (!(SrcTy.getScalarType().isAnyScalar() ||
10639 SrcTy.getScalarType().isInteger())) {
10641 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10642 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10645 if (MRI.getType(DstReg) != TyInt) {
10649 .buildAnd(TyInt, CastedSrc,
10652 DstTy.getScalarSizeInBits())))
10664 MI.eraseFromParent();
10670 Register SrcReg =
MI.getOperand(1).getReg();
10671 LLT SrcTy = MRI.getType(SrcReg);
10672 LLT DstTy = MRI.getType(SrcReg);
10675 if (SrcTy.isScalar()) {
10680 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10691 Register ListPtr =
MI.getOperand(1).getReg();
10692 LLT PtrTy = MRI.getType(ListPtr);
10699 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10701 const Align A(
MI.getOperand(2).getImm());
10703 if (
A > TLI.getMinStackArgumentAlignment()) {
10705 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10706 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10707 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10708 VAList = AndDst.getReg(0);
10715 LLT LLTTy = MRI.getType(Dst);
10718 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10719 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10724 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10726 Align EltAlignment =
DL.getABITypeAlign(Ty);
10729 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10731 MI.eraseFromParent();
10736 [[maybe_unused]]
unsigned OpCode =
MI.getOpcode();
10737 assert((OpCode == TargetOpcode::G_SMULFIX ||
10738 OpCode == TargetOpcode::G_UMULFIX) &&
10739 "Operator must be either G_SMULFIX or G_UMULFIX!");
10740 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10741 LLT Ty = MRI.getType(Dst);
10742 unsigned Scale =
MI.getOperand(3).getImm();
10746 MI.eraseFromParent();
10752 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
10754 if (
MI.getOpcode() == TargetOpcode::G_SMULFIX) {
10763 if (
MI.getOpcode() == TargetOpcode::G_SMULFIX)
10770 MI.eraseFromParent();
10777 unsigned NumBits = Ty.getScalarSizeInBits();
10779 if (!Ty.isVector() && ValVRegAndVal) {
10780 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10788 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10809 uint64_t KnownLen,
Align Alignment,
10811 auto &MF = *
MI.getParent()->getParent();
10816 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10817 assert(!MemOps.
empty() &&
"Expected at least one memory op");
10820 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10821 const auto &DstMMO = **
MI.memoperands_begin();
10823 if (DstAlignCanChange) {
10826 Align NewAlign =
DL.getABITypeAlign(IRTy);
10827 if (NewAlign > Alignment) {
10828 Alignment = NewAlign;
10836 MachineIRBuilder MIB(
MI);
10838 LLT LargestTy = MemOps[0];
10839 for (
unsigned i = 1; i < MemOps.
size(); i++)
10841 LargestTy = MemOps[i];
10853 LLT PtrTy = MRI.getType(Dst);
10854 unsigned DstOff = 0;
10855 unsigned Size = KnownLen;
10856 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
10857 LLT Ty = MemOps[
I];
10859 if (TySize >
Size) {
10863 DstOff -= TySize -
Size;
10873 TLI.isTruncateFree(LargestVT, VT))
10874 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10887 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10890 MIB.buildStore(
Value, Ptr, *StoreMMO);
10895 MI.eraseFromParent();
10901 uint64_t KnownLen,
Align Alignment,
10903 auto &MF = *
MI.getParent()->getParent();
10907 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10908 assert(!MemOps.
empty() &&
"Expected at least one memory op");
10911 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10917 const auto &DstMMO = **
MI.memoperands_begin();
10918 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10920 if (DstAlignCanChange) {
10923 Align NewAlign =
DL.getABITypeAlign(IRTy);
10928 if (!
TRI->hasStackRealignment(MF))
10929 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10930 NewAlign = std::min(NewAlign, *StackAlign);
10932 if (NewAlign > Alignment) {
10933 Alignment = NewAlign;
10941 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10943 MachineIRBuilder MIB(
MI);
10949 unsigned CurrOffset = 0;
10950 unsigned Size = KnownLen;
10951 for (
auto CopyTy : MemOps) {
10954 if (CopyTy.getSizeInBytes() >
Size)
10955 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10966 if (CurrOffset != 0) {
10967 LLT SrcTy = MRI.getType(Src);
10971 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10973 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10977 if (CurrOffset != 0) {
10978 LLT DstTy = MRI.getType(Dst);
10979 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10981 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10982 CurrOffset += CopyTy.getSizeInBytes();
10983 Size -= CopyTy.getSizeInBytes();
10986 MI.eraseFromParent();
10992 uint64_t KnownLen,
Align Alignment,
10994 auto &MF = *
MI.getParent()->getParent();
10998 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10999 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11002 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11003 const auto &DstMMO = **
MI.memoperands_begin();
11004 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11006 if (DstAlignCanChange) {
11009 Align NewAlign =
DL.getABITypeAlign(IRTy);
11014 if (!
TRI->hasStackRealignment(MF))
11015 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11016 NewAlign = std::min(NewAlign, *StackAlign);
11018 if (NewAlign > Alignment) {
11019 Alignment = NewAlign;
11027 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11029 MachineIRBuilder MIB(
MI);
11033 unsigned CurrOffset = 0;
11034 SmallVector<Register, 16> LoadVals;
11035 for (
auto CopyTy : MemOps) {
11042 if (CurrOffset != 0) {
11043 LLT SrcTy = MRI.getType(Src);
11046 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11048 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11049 CurrOffset += CopyTy.getSizeInBytes();
11053 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11054 LLT CopyTy = MemOps[
I];
11060 if (CurrOffset != 0) {
11061 LLT DstTy = MRI.getType(Dst);
11064 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11066 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11069 MI.eraseFromParent();
11076 const unsigned Opc =
MI.getOpcode();
11077 assert((
Opc == TargetOpcode::G_MEMCPY ||
11078 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11079 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11080 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11081 "Expected memcpy like instruction");
11083 if (KnownLen == 0) {
11084 MI.eraseFromParent();
11088 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11089 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11092 if (
Opc == TargetOpcode::G_MEMMOVE)
11093 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11095 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11096 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11106 bool DstAlignCanChange;
11107 std::vector<LLT> MemOps;
11109 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 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 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 Register coerceToScalar(Register Val)
Cast the given value to an LLT::scalar with an equivalent size.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
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 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.
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 std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
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.