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())
2286 else if (DstTy != WideTy)
2289 MI.eraseFromParent();
2314 const int GCD = std::gcd(SrcSize, WideSize);
2324 if (GCD == SrcSize) {
2327 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2328 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2334 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2336 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2340 const int PartsPerGCD = WideSize / GCD;
2344 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2346 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2353 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2355 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2356 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2359 MI.eraseFromParent();
2364LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2369 int NumDst =
MI.getNumOperands() - 1;
2370 Register SrcReg =
MI.getOperand(NumDst).getReg();
2371 LLT SrcTy = MRI.getType(SrcReg);
2375 Register Dst0Reg =
MI.getOperand(0).getReg();
2376 LLT DstTy = MRI.getType(Dst0Reg);
2385 dbgs() <<
"Not casting non-integral address space integer\n");
2390 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2398 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2406 for (
int I = 1;
I != NumDst; ++
I) {
2407 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2408 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2412 MI.eraseFromParent();
2423 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2427 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2430 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2448 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2453 if (PartsPerRemerge == 1) {
2456 for (
int I = 0;
I != NumUnmerge; ++
I) {
2457 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2459 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2460 int Idx =
I * PartsPerUnmerge + J;
2462 MIB.addDef(
MI.getOperand(Idx).getReg());
2465 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2469 MIB.addUse(Unmerge.getReg(
I));
2472 SmallVector<Register, 16> Parts;
2473 for (
int J = 0; J != NumUnmerge; ++J)
2474 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2477 for (
int I = 0;
I != NumDst; ++
I) {
2478 for (
int J = 0; J < PartsPerRemerge; ++J) {
2479 const int Idx =
I * PartsPerRemerge + J;
2483 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2484 RemergeParts.
clear();
2488 MI.eraseFromParent();
2493LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2495 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2496 unsigned Offset =
MI.getOperand(2).getImm();
2499 if (SrcTy.
isVector() || DstTy.isVector())
2511 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2515 if (DstTy.isPointer())
2522 MI.eraseFromParent();
2527 LLT ShiftTy = SrcTy;
2536 MI.eraseFromParent();
2567LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2569 if (TypeIdx != 0 || WideTy.
isVector())
2579LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2583 std::optional<Register> CarryIn;
2584 switch (
MI.getOpcode()) {
2587 case TargetOpcode::G_SADDO:
2588 Opcode = TargetOpcode::G_ADD;
2589 ExtOpcode = TargetOpcode::G_SEXT;
2591 case TargetOpcode::G_SSUBO:
2592 Opcode = TargetOpcode::G_SUB;
2593 ExtOpcode = TargetOpcode::G_SEXT;
2595 case TargetOpcode::G_UADDO:
2596 Opcode = TargetOpcode::G_ADD;
2597 ExtOpcode = TargetOpcode::G_ZEXT;
2599 case TargetOpcode::G_USUBO:
2600 Opcode = TargetOpcode::G_SUB;
2601 ExtOpcode = TargetOpcode::G_ZEXT;
2603 case TargetOpcode::G_SADDE:
2604 Opcode = TargetOpcode::G_UADDE;
2605 ExtOpcode = TargetOpcode::G_SEXT;
2606 CarryIn =
MI.getOperand(4).getReg();
2608 case TargetOpcode::G_SSUBE:
2609 Opcode = TargetOpcode::G_USUBE;
2610 ExtOpcode = TargetOpcode::G_SEXT;
2611 CarryIn =
MI.getOperand(4).getReg();
2613 case TargetOpcode::G_UADDE:
2614 Opcode = TargetOpcode::G_UADDE;
2615 ExtOpcode = TargetOpcode::G_ZEXT;
2616 CarryIn =
MI.getOperand(4).getReg();
2618 case TargetOpcode::G_USUBE:
2619 Opcode = TargetOpcode::G_USUBE;
2620 ExtOpcode = TargetOpcode::G_ZEXT;
2621 CarryIn =
MI.getOperand(4).getReg();
2637 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2638 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2642 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2644 .buildInstr(Opcode, {WideTy, CarryOutTy},
2645 {LHSExt, RHSExt, *CarryIn})
2648 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2650 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2651 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2652 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2657 MI.eraseFromParent();
2662LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2664 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2665 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2666 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2667 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2668 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2681 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2688 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2692 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2693 {ShiftL, ShiftR},
MI.getFlags());
2698 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2701 MI.eraseFromParent();
2706LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2715 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2717 LLT SrcTy = MRI.getType(
LHS);
2718 LLT OverflowTy = MRI.getType(OriginalOverflow);
2725 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2726 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2727 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2734 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2736 MachineInstrBuilder Mulo;
2737 if (WideMulCanOverflow)
2738 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2739 {LeftOperand, RightOperand});
2741 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2746 MachineInstrBuilder ExtResult;
2753 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2757 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2760 if (WideMulCanOverflow) {
2768 MI.eraseFromParent();
2774 unsigned Opcode =
MI.getOpcode();
2778 case TargetOpcode::G_ATOMICRMW_XCHG:
2779 case TargetOpcode::G_ATOMICRMW_ADD:
2780 case TargetOpcode::G_ATOMICRMW_SUB:
2781 case TargetOpcode::G_ATOMICRMW_AND:
2782 case TargetOpcode::G_ATOMICRMW_OR:
2783 case TargetOpcode::G_ATOMICRMW_XOR:
2784 case TargetOpcode::G_ATOMICRMW_MIN:
2785 case TargetOpcode::G_ATOMICRMW_MAX:
2786 case TargetOpcode::G_ATOMICRMW_UMIN:
2787 case TargetOpcode::G_ATOMICRMW_UMAX:
2788 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2794 case TargetOpcode::G_ATOMIC_CMPXCHG:
2795 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2802 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2812 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2817 case TargetOpcode::G_EXTRACT:
2818 return widenScalarExtract(
MI, TypeIdx, WideTy);
2819 case TargetOpcode::G_INSERT:
2820 return widenScalarInsert(
MI, TypeIdx, WideTy);
2821 case TargetOpcode::G_MERGE_VALUES:
2822 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2823 case TargetOpcode::G_UNMERGE_VALUES:
2824 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2825 case TargetOpcode::G_SADDO:
2826 case TargetOpcode::G_SSUBO:
2827 case TargetOpcode::G_UADDO:
2828 case TargetOpcode::G_USUBO:
2829 case TargetOpcode::G_SADDE:
2830 case TargetOpcode::G_SSUBE:
2831 case TargetOpcode::G_UADDE:
2832 case TargetOpcode::G_USUBE:
2833 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2834 case TargetOpcode::G_UMULO:
2835 case TargetOpcode::G_SMULO:
2836 return widenScalarMulo(
MI, TypeIdx, WideTy);
2837 case TargetOpcode::G_SADDSAT:
2838 case TargetOpcode::G_SSUBSAT:
2839 case TargetOpcode::G_SSHLSAT:
2840 case TargetOpcode::G_UADDSAT:
2841 case TargetOpcode::G_USUBSAT:
2842 case TargetOpcode::G_USHLSAT:
2843 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2844 case TargetOpcode::G_CTTZ:
2845 case TargetOpcode::G_CTTZ_ZERO_POISON:
2846 case TargetOpcode::G_CTLZ:
2847 case TargetOpcode::G_CTLZ_ZERO_POISON:
2848 case TargetOpcode::G_CTLS:
2849 case TargetOpcode::G_CTPOP: {
2862 case TargetOpcode::G_CTTZ:
2863 case TargetOpcode::G_CTTZ_ZERO_POISON:
2864 case TargetOpcode::G_CTLZ_ZERO_POISON:
2865 ExtOpc = TargetOpcode::G_ANYEXT;
2867 case TargetOpcode::G_CTLS:
2868 ExtOpc = TargetOpcode::G_SEXT;
2871 ExtOpc = TargetOpcode::G_ZEXT;
2874 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2875 LLT CurTy = MRI.getType(SrcReg);
2876 unsigned NewOpc = Opcode;
2877 if (NewOpc == TargetOpcode::G_CTTZ) {
2884 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2886 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2892 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2902 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2904 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2909 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2910 Opcode == TargetOpcode::G_CTLZ
2915 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2916 MI.eraseFromParent();
2919 case TargetOpcode::G_BSWAP: {
2923 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2924 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2925 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2928 MI.getOperand(0).setReg(DstExt);
2932 LLT Ty = MRI.getType(DstReg);
2934 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2935 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2941 case TargetOpcode::G_BITREVERSE: {
2945 LLT Ty = MRI.getType(DstReg);
2948 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2950 MI.getOperand(0).setReg(DstExt);
2953 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2954 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2959 case TargetOpcode::G_FREEZE:
2960 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2967 case TargetOpcode::G_ABS:
2974 case TargetOpcode::G_ADD:
2975 case TargetOpcode::G_AND:
2976 case TargetOpcode::G_MUL:
2977 case TargetOpcode::G_OR:
2978 case TargetOpcode::G_XOR:
2979 case TargetOpcode::G_SUB:
2980 case TargetOpcode::G_SHUFFLE_VECTOR:
2991 case TargetOpcode::G_SBFX:
2992 case TargetOpcode::G_UBFX:
3006 case TargetOpcode::G_SHL:
3022 case TargetOpcode::G_ROTR:
3023 case TargetOpcode::G_ROTL:
3032 case TargetOpcode::G_SDIV:
3033 case TargetOpcode::G_SREM:
3034 case TargetOpcode::G_SMIN:
3035 case TargetOpcode::G_SMAX:
3036 case TargetOpcode::G_ABDS:
3044 case TargetOpcode::G_SDIVREM:
3054 case TargetOpcode::G_ASHR:
3055 case TargetOpcode::G_LSHR:
3059 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3060 : TargetOpcode::G_ZEXT;
3073 case TargetOpcode::G_UDIV:
3074 case TargetOpcode::G_UREM:
3075 case TargetOpcode::G_ABDU:
3082 case TargetOpcode::G_UDIVREM:
3091 case TargetOpcode::G_UMIN:
3092 case TargetOpcode::G_UMAX: {
3093 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3095 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3099 ? TargetOpcode::G_SEXT
3100 : TargetOpcode::G_ZEXT;
3110 case TargetOpcode::G_SELECT:
3120 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3127 case TargetOpcode::G_FPEXT:
3135 case TargetOpcode::G_FPTOSI:
3136 case TargetOpcode::G_FPTOUI:
3137 case TargetOpcode::G_INTRINSIC_LRINT:
3138 case TargetOpcode::G_INTRINSIC_LLRINT:
3139 case TargetOpcode::G_IS_FPCLASS:
3149 case TargetOpcode::G_SITOFP:
3159 case TargetOpcode::G_UITOFP:
3169 case TargetOpcode::G_FPTOSI_SAT:
3170 case TargetOpcode::G_FPTOUI_SAT:
3175 LLT Ty = MRI.getType(OldDst);
3176 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3178 MI.getOperand(0).setReg(ExtReg);
3179 uint64_t ShortBits = Ty.getScalarSizeInBits();
3182 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3193 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3194 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3202 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3210 case TargetOpcode::G_LOAD:
3211 case TargetOpcode::G_SEXTLOAD:
3212 case TargetOpcode::G_ZEXTLOAD:
3213 case TargetOpcode::G_FPEXTLOAD:
3219 case TargetOpcode::G_STORE: {
3223 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3224 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3225 if (!Ty.isScalar()) {
3233 MI.setMemRefs(MF, {NewMMO});
3240 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3241 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3247 case TargetOpcode::G_FPTRUNCSTORE:
3254 case TargetOpcode::G_CONSTANT: {
3257 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3258 MRI.getType(
MI.getOperand(0).getReg()));
3259 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3260 ExtOpc == TargetOpcode::G_ANYEXT) &&
3263 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3267 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3273 case TargetOpcode::G_FCONSTANT: {
3279 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3281 MI.eraseFromParent();
3284 case TargetOpcode::G_IMPLICIT_DEF: {
3290 case TargetOpcode::G_BRCOND:
3296 case TargetOpcode::G_FCMP:
3307 case TargetOpcode::G_ICMP:
3312 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3316 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3317 unsigned ExtOpcode =
3321 ? TargetOpcode::G_SEXT
3322 : TargetOpcode::G_ZEXT;
3329 case TargetOpcode::G_PTR_ADD:
3330 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3336 case TargetOpcode::G_PHI: {
3337 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3340 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3352 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3355 LLT VecTy = MRI.getType(VecReg);
3359 TargetOpcode::G_ANYEXT);
3373 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3389 LLT VecTy = MRI.getType(VecReg);
3408 case TargetOpcode::G_FADD:
3409 case TargetOpcode::G_FMUL:
3410 case TargetOpcode::G_FSUB:
3411 case TargetOpcode::G_FMA:
3412 case TargetOpcode::G_FMAD:
3413 case TargetOpcode::G_FNEG:
3414 case TargetOpcode::G_FABS:
3415 case TargetOpcode::G_FCANONICALIZE:
3416 case TargetOpcode::G_FMINNUM:
3417 case TargetOpcode::G_FMAXNUM:
3418 case TargetOpcode::G_FMINNUM_IEEE:
3419 case TargetOpcode::G_FMAXNUM_IEEE:
3420 case TargetOpcode::G_FMINIMUM:
3421 case TargetOpcode::G_FMAXIMUM:
3422 case TargetOpcode::G_FMINIMUMNUM:
3423 case TargetOpcode::G_FMAXIMUMNUM:
3424 case TargetOpcode::G_FDIV:
3425 case TargetOpcode::G_FREM:
3426 case TargetOpcode::G_FCEIL:
3427 case TargetOpcode::G_FFLOOR:
3428 case TargetOpcode::G_FCOS:
3429 case TargetOpcode::G_FSIN:
3430 case TargetOpcode::G_FTAN:
3431 case TargetOpcode::G_FACOS:
3432 case TargetOpcode::G_FASIN:
3433 case TargetOpcode::G_FATAN:
3434 case TargetOpcode::G_FATAN2:
3435 case TargetOpcode::G_FCOSH:
3436 case TargetOpcode::G_FSINH:
3437 case TargetOpcode::G_FTANH:
3438 case TargetOpcode::G_FLOG10:
3439 case TargetOpcode::G_FLOG:
3440 case TargetOpcode::G_FLOG2:
3441 case TargetOpcode::G_FRINT:
3442 case TargetOpcode::G_FNEARBYINT:
3443 case TargetOpcode::G_FSQRT:
3444 case TargetOpcode::G_FEXP:
3445 case TargetOpcode::G_FEXP2:
3446 case TargetOpcode::G_FEXP10:
3447 case TargetOpcode::G_FPOW:
3448 case TargetOpcode::G_INTRINSIC_TRUNC:
3449 case TargetOpcode::G_INTRINSIC_ROUND:
3450 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3454 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3460 case TargetOpcode::G_FMODF: {
3470 case TargetOpcode::G_FPOWI:
3471 case TargetOpcode::G_FLDEXP:
3472 case TargetOpcode::G_STRICT_FLDEXP: {
3474 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3495 case TargetOpcode::G_FFREXP: {
3508 case TargetOpcode::G_LROUND:
3509 case TargetOpcode::G_LLROUND:
3520 case TargetOpcode::G_INTTOPTR:
3528 case TargetOpcode::G_PTRTOINT:
3536 case TargetOpcode::G_BUILD_VECTOR: {
3540 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3546 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3554 case TargetOpcode::G_SEXT_INREG:
3563 case TargetOpcode::G_PTRMASK: {
3571 case TargetOpcode::G_VECREDUCE_ADD: {
3580 case TargetOpcode::G_VECREDUCE_FADD:
3581 case TargetOpcode::G_VECREDUCE_FMUL:
3582 case TargetOpcode::G_VECREDUCE_FMIN:
3583 case TargetOpcode::G_VECREDUCE_FMAX:
3584 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3585 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3590 LLT VecTy = MRI.getType(VecReg);
3597 case TargetOpcode::G_VSCALE: {
3604 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3609 case TargetOpcode::G_SPLAT_VECTOR: {
3618 case TargetOpcode::G_INSERT_SUBVECTOR: {
3626 LLT SubVecTy = MRI.getType(SubVec);
3630 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3631 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3632 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3636 auto SplatZero =
MIRBuilder.buildSplatVector(
3641 MI.eraseFromParent();
3645 case TargetOpcode::G_BITCAST:
3657 if (MRI.getType(Dst) == MRI.getType(Src)) {
3658 Observer.changingAllUsesOfReg(MRI, Dst);
3659 MRI.replaceRegWith(Dst, Src);
3660 Observer.finishedChangingAllUsesOfReg();
3661 MI.eraseFromParent();
3670 auto Unmerge =
B.buildUnmerge(Ty, Src);
3671 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3680 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3694 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3703 MI.eraseFromParent();
3714 MI.eraseFromParent();
3721 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3722 if (SrcTy.isVector()) {
3726 if (DstTy.isVector()) {
3727 int NumDstElt = DstTy.getNumElements();
3728 int NumSrcElt = SrcTy.getNumElements();
3731 LLT DstCastTy = DstEltTy;
3732 LLT SrcPartTy = SrcEltTy;
3736 if (NumSrcElt < NumDstElt) {
3747 SrcPartTy = SrcEltTy;
3748 }
else if (NumSrcElt > NumDstElt) {
3760 DstCastTy = DstEltTy;
3765 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3769 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3770 MI.eraseFromParent();
3774 if (DstTy.isVector()) {
3777 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3778 MI.eraseFromParent();
3794 unsigned NewEltSize,
3795 unsigned OldEltSize) {
3796 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3797 LLT IdxTy =
B.getMRI()->getType(Idx);
3800 auto OffsetMask =
B.buildConstant(
3802 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3803 return B.buildShl(IdxTy, OffsetIdx,
3804 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3819 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3823 unsigned OldNumElts = SrcVecTy.getNumElements();
3830 if (NewNumElts > OldNumElts) {
3841 if (NewNumElts % OldNumElts != 0)
3845 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3849 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3852 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3854 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3855 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3856 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3857 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3858 NewOps[
I] = Elt.getReg(0);
3861 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3863 MI.eraseFromParent();
3867 if (NewNumElts < OldNumElts) {
3868 if (NewEltSize % OldEltSize != 0)
3890 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3891 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3894 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3898 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3899 ScaledIdx).getReg(0);
3907 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3909 MI.eraseFromParent();
3923 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3924 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3925 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3926 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3929 auto EltMask =
B.buildConstant(
3933 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3934 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3937 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3941 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3955 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3956 MI.getFirst4RegLLTs();
3968 if (NewNumElts < OldNumElts) {
3969 if (NewEltSize % OldEltSize != 0)
3978 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3979 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3982 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3986 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3987 ScaledIdx).getReg(0);
3997 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3998 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4002 MI.eraseFromParent();
4032 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4036 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4037 return UnableToLegalize;
4042 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4044 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4053 MI.eraseFromParent();
4071 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4072 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4082 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4083 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4085 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4086 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4088 MI.eraseFromParent();
4118 LLT DstTy = MRI.getType(Dst);
4119 LLT SrcTy = MRI.getType(Src);
4125 if (DstTy == CastTy)
4133 if (CastEltSize < DstEltSize)
4136 auto AdjustAmt = CastEltSize / DstEltSize;
4137 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4138 SrcTyMinElts % AdjustAmt != 0)
4143 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4144 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4147 ES->eraseFromParent();
4182 LLT DstTy = MRI.getType(Dst);
4183 LLT BigVecTy = MRI.getType(BigVec);
4184 LLT SubVecTy = MRI.getType(SubVec);
4186 if (DstTy == CastTy)
4201 if (CastEltSize < DstEltSize)
4204 auto AdjustAmt = CastEltSize / DstEltSize;
4205 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4206 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4212 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4213 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4215 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4218 ES->eraseFromParent();
4226 LLT DstTy = MRI.getType(DstReg);
4236 if (MemSizeInBits != MemStoreSizeInBits) {
4253 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4257 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4258 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4260 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4263 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4265 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4268 if (DstTy != LoadTy)
4276 if (
MIRBuilder.getDataLayout().isBigEndian())
4294 uint64_t LargeSplitSize, SmallSplitSize;
4299 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4306 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4309 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4320 if (Alignment.
value() * 8 > MemSizeInBits &&
4325 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4342 LLT PtrTy = MRI.getType(PtrReg);
4355 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4358 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4359 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4360 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4362 SmallPtr, *SmallMMO);
4364 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4365 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4367 if (AnyExtTy == DstTy)
4368 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4370 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4374 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4394 LLT SrcTy = MRI.getType(SrcReg);
4402 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4408 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4410 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4414 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4418 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4433 uint64_t LargeSplitSize, SmallSplitSize;
4440 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4443 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4452 if (SrcTy.isPointer()) {
4457 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4460 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4461 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4464 LLT PtrTy = MRI.getType(PtrReg);
4466 LargeSplitSize / 8);
4467 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4473 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4474 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4483 LLT SrcTy = MRI.getType(SrcReg);
4489 assert(SrcTy.isVector() &&
"Expect a vector store type");
4496 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4500 auto Elt =
MIRBuilder.buildExtractVectorElement(
4501 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4502 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4503 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4509 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4510 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4514 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4525 switch (
MI.getOpcode()) {
4526 case TargetOpcode::G_LOAD: {
4544 case TargetOpcode::G_STORE: {
4560 case TargetOpcode::G_SELECT: {
4564 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4566 dbgs() <<
"bitcast action not implemented for vector select\n");
4577 case TargetOpcode::G_AND:
4578 case TargetOpcode::G_OR:
4579 case TargetOpcode::G_XOR: {
4587 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4589 case TargetOpcode::G_INSERT_VECTOR_ELT:
4591 case TargetOpcode::G_CONCAT_VECTORS:
4593 case TargetOpcode::G_SHUFFLE_VECTOR:
4595 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4597 case TargetOpcode::G_INSERT_SUBVECTOR:
4605void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4614 switch(
MI.getOpcode()) {
4617 case TargetOpcode::G_FCONSTANT:
4619 case TargetOpcode::G_BITCAST:
4621 case TargetOpcode::G_SREM:
4622 case TargetOpcode::G_UREM: {
4623 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4625 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4626 {MI.getOperand(1), MI.getOperand(2)});
4628 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4630 MI.eraseFromParent();
4633 case TargetOpcode::G_SADDO:
4634 case TargetOpcode::G_SSUBO:
4636 case TargetOpcode::G_SADDE:
4638 case TargetOpcode::G_SSUBE:
4640 case TargetOpcode::G_UMULH:
4641 case TargetOpcode::G_SMULH:
4643 case TargetOpcode::G_SMULO:
4644 case TargetOpcode::G_UMULO: {
4647 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4648 LLT Ty = MRI.getType(Res);
4650 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4651 ? TargetOpcode::G_SMULH
4652 : TargetOpcode::G_UMULH;
4656 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4657 MI.removeOperand(1);
4660 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4668 if (Opcode == TargetOpcode::G_SMULH) {
4669 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4670 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4677 case TargetOpcode::G_FNEG: {
4678 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4681 Register CastedSubByReg = SubByReg;
4683 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4684 !SubByRegTy.getScalarType().isInteger()) {
4685 auto BitcastDst = SubByRegTy.changeElementType(
4687 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4693 if (ResTy != TyInt) {
4695 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4698 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4700 MI.eraseFromParent();
4703 case TargetOpcode::G_FSUB:
4704 case TargetOpcode::G_STRICT_FSUB: {
4705 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4706 LLT Ty = MRI.getType(Res);
4711 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4712 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4716 MI.eraseFromParent();
4719 case TargetOpcode::G_FMAD:
4721 case TargetOpcode::G_FFLOOR:
4723 case TargetOpcode::G_LROUND:
4724 case TargetOpcode::G_LLROUND: {
4727 LLT SrcTy = MRI.getType(SrcReg);
4728 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4731 MI.eraseFromParent();
4734 case TargetOpcode::G_INTRINSIC_ROUND:
4736 case TargetOpcode::G_FRINT: {
4739 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4742 case TargetOpcode::G_INTRINSIC_LRINT:
4743 case TargetOpcode::G_INTRINSIC_LLRINT: {
4746 LLT SrcTy = MRI.getType(SrcReg);
4748 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4750 MI.eraseFromParent();
4753 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4754 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4755 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4756 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4757 **
MI.memoperands_begin());
4759 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4760 MI.eraseFromParent();
4763 case TargetOpcode::G_LOAD:
4764 case TargetOpcode::G_SEXTLOAD:
4765 case TargetOpcode::G_ZEXTLOAD:
4767 case TargetOpcode::G_STORE:
4769 case TargetOpcode::G_CTLZ_ZERO_POISON:
4770 case TargetOpcode::G_CTTZ_ZERO_POISON:
4771 case TargetOpcode::G_CTLZ:
4772 case TargetOpcode::G_CTTZ:
4773 case TargetOpcode::G_CTPOP:
4774 case TargetOpcode::G_CTLS:
4777 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4779 Register NewRes = MRI.cloneVirtualRegister(Res);
4786 MI.eraseFromParent();
4790 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4791 const LLT CondTy = MRI.getType(CarryOut);
4792 const LLT Ty = MRI.getType(Res);
4794 Register NewRes = MRI.cloneVirtualRegister(Res);
4797 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4803 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4804 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4811 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4816 MI.eraseFromParent();
4820 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4825 MI.eraseFromParent();
4829 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4830 const LLT CondTy = MRI.getType(BorrowOut);
4831 const LLT Ty = MRI.getType(Res);
4834 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4840 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4841 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4848 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4849 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4851 MI.eraseFromParent();
4891 case G_MERGE_VALUES:
4893 case G_UNMERGE_VALUES:
4895 case TargetOpcode::G_SEXT_INREG: {
4896 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4897 int64_t SizeInBits =
MI.getOperand(2).getImm();
4899 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4900 LLT DstTy = MRI.getType(DstReg);
4901 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4904 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4905 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4906 MI.eraseFromParent();
4909 case G_EXTRACT_VECTOR_ELT:
4910 case G_INSERT_VECTOR_ELT:
4912 case G_SHUFFLE_VECTOR:
4914 case G_VECTOR_COMPRESS:
4916 case G_DYN_STACKALLOC:
4918 case G_INSERT_SUBVECTOR: {
4919 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4920 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4925 Register Subvector =
MI.getOperand(2).getReg();
4926 auto InsertionPointImm =
MI.getOperand(3).getImm();
4929 LLT SubvectorTy = MRI.getType(Subvector);
4933 bool InsertInLowHalf = InsertionPointImm == 0;
4934 auto Extract =
MIRBuilder.buildExtractSubvector(
4938 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4939 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4941 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4942 {LowHalf, HighHalf});
4943 MI.eraseFromParent();
4949 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4950 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4956 if (i >= InsertionPointImm &&
4958 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
4966 MI.eraseFromParent();
4972 case G_STACKRESTORE:
4982 case G_READ_REGISTER:
4983 case G_WRITE_REGISTER:
4990 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4991 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4997 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5002 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5013 bool IsSigned =
MI.getOpcode() == G_ABDS;
5014 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5015 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5016 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5039 case G_MEMCPY_INLINE:
5040 case G_MEMSET_INLINE:
5052 case G_ATOMICRMW_SUB: {
5053 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5054 const LLT ValTy = MRI.getType(Val);
5058 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5059 MI.eraseFromParent();
5085 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5089 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5095 Align StackTypeAlign =
5102 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5103 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5108 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5120 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
5123 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5134 "Converting bits to bytes lost precision");
5140 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5141 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5143 if (IdxTy != MRI.getType(Index))
5144 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5149 LLT PtrTy = MRI.getType(VecPtr);
5150 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5158 std::initializer_list<unsigned> NonVecOpIndices) {
5159 if (
MI.getNumMemOperands() != 0)
5176 if (!Ty.isVector()) {
5182 if (Ty.getNumElements() != NumElts)
5197 assert(Ty.isVector() &&
"Expected vector type");
5199 int NumParts, NumLeftover;
5200 std::tie(NumParts, NumLeftover) =
5203 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5204 for (
int i = 0; i < NumParts; ++i) {
5209 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5218 for (
unsigned i = 0; i <
N; ++i) {
5220 Ops.push_back(
Op.getReg());
5221 else if (
Op.isImm())
5222 Ops.push_back(
Op.getImm());
5223 else if (
Op.isPredicate())
5245 std::initializer_list<unsigned> NonVecOpIndices) {
5247 "Non-compatible opcode or not specified non-vector operands");
5248 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5250 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5251 unsigned NumDefs =
MI.getNumDefs();
5259 for (
unsigned i = 0; i < NumDefs; ++i) {
5260 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5268 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5269 ++UseIdx, ++UseNo) {
5272 MI.getOperand(UseIdx));
5281 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5285 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5287 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5288 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5291 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5292 Uses.push_back(InputOpsPieces[InputNo][i]);
5295 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5296 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5301 for (
unsigned i = 0; i < NumDefs; ++i)
5302 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5304 for (
unsigned i = 0; i < NumDefs; ++i)
5305 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5308 MI.eraseFromParent();
5315 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5317 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5318 unsigned NumDefs =
MI.getNumDefs();
5322 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5327 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5328 UseIdx += 2, ++UseNo) {
5336 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5338 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5339 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5341 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5344 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5345 Phi.addUse(InputOpsPieces[j][i]);
5346 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5356 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5358 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5361 MI.eraseFromParent();
5369 const int NumDst =
MI.getNumOperands() - 1;
5370 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5371 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5372 LLT SrcTy = MRI.getType(SrcReg);
5374 if (TypeIdx != 1 || NarrowTy == DstTy)
5381 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5384 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5398 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5399 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5400 const int PartsPerUnmerge = NumDst / NumUnmerge;
5402 for (
int I = 0;
I != NumUnmerge; ++
I) {
5403 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5405 for (
int J = 0; J != PartsPerUnmerge; ++J)
5406 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5407 MIB.addUse(Unmerge.getReg(
I));
5410 MI.eraseFromParent();
5417 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5421 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5423 if (NarrowTy == SrcTy)
5431 assert(SrcTy.isVector() &&
"Expected vector types");
5433 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5447 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5448 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5449 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5455 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5456 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5457 ++i,
Offset += NumNarrowTyElts) {
5460 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5463 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5464 MI.eraseFromParent();
5468 assert(TypeIdx == 0 &&
"Bad type index");
5469 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5484 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5485 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5487 for (
unsigned i = 0; i < NumParts; ++i) {
5489 for (
unsigned j = 0; j < NumElts; ++j)
5490 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5492 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5495 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5496 MI.eraseFromParent();
5504 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5506 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5508 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5510 InsertVal =
MI.getOperand(2).getReg();
5512 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5513 LLT VecTy = MRI.getType(SrcVec);
5519 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5523 MI.eraseFromParent();
5532 SplitPieces[IdxVal] = InsertVal;
5533 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5535 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5539 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5542 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5543 TargetOpcode::G_ANYEXT);
5547 LLT IdxTy = MRI.getType(Idx);
5548 int64_t PartIdx = IdxVal / NewNumElts;
5550 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5553 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5556 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5557 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5558 VecParts[PartIdx] = InsertPart.getReg(0);
5562 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5564 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5568 MI.eraseFromParent();
5588 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5600 LLT ValTy = MRI.getType(ValReg);
5609 int NumLeftover = -1;
5615 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5617 NumParts = NarrowRegs.
size();
5618 NumLeftover = NarrowLeftoverRegs.
size();
5625 LLT PtrTy = MRI.getType(AddrReg);
5635 auto MMO = LdStMI.
getMMO();
5637 unsigned NumParts,
unsigned Offset) ->
unsigned {
5640 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5642 unsigned ByteOffset =
Offset / 8;
5645 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5652 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5653 ValRegs.push_back(Dst);
5654 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5656 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5665 unsigned HandledOffset =
5666 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5670 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5673 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5674 LeftoverTy, NarrowLeftoverRegs);
5688 switch (
MI.getOpcode()) {
5689 case G_IMPLICIT_DEF:
5705 case G_FCANONICALIZE:
5722 case G_INTRINSIC_LRINT:
5723 case G_INTRINSIC_LLRINT:
5724 case G_INTRINSIC_ROUND:
5725 case G_INTRINSIC_ROUNDEVEN:
5728 case G_INTRINSIC_TRUNC:
5756 case G_FMINNUM_IEEE:
5757 case G_FMAXNUM_IEEE:
5779 case G_CTLZ_ZERO_POISON:
5781 case G_CTTZ_ZERO_POISON:
5798 case G_ADDRSPACE_CAST:
5811 case G_STRICT_FLDEXP:
5813 case G_TRUNC_SSAT_S:
5814 case G_TRUNC_SSAT_U:
5815 case G_TRUNC_USAT_U:
5823 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5828 case G_UNMERGE_VALUES:
5830 case G_BUILD_VECTOR:
5831 assert(TypeIdx == 0 &&
"not a vector type index");
5833 case G_CONCAT_VECTORS:
5837 case G_EXTRACT_VECTOR_ELT:
5838 case G_INSERT_VECTOR_ELT:
5847 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5848 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5850 case G_SHUFFLE_VECTOR:
5856 case G_INTRINSIC_FPTRUNC_ROUND:
5866 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5867 "Not a bitcast operation");
5872 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5874 unsigned NewElemCount =
5877 if (NewElemCount == 1) {
5880 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5887 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5896 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5897 MI.eraseFromParent();
5903 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5907 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5908 MI.getFirst3RegLLTs();
5911 if (DstTy != Src1Ty)
5913 if (DstTy != Src2Ty)
5928 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5944 unsigned InputUsed[2] = {-1U, -1U};
5945 unsigned FirstMaskIdx =
High * NewElts;
5946 bool UseBuildVector =
false;
5947 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5949 int Idx = Mask[FirstMaskIdx + MaskOffset];
5954 if (
Input >= std::size(Inputs)) {
5961 Idx -=
Input * NewElts;
5965 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5966 if (InputUsed[OpNo] ==
Input) {
5969 }
else if (InputUsed[OpNo] == -1U) {
5971 InputUsed[OpNo] =
Input;
5976 if (OpNo >= std::size(InputUsed)) {
5979 UseBuildVector =
true;
5984 Ops.push_back(Idx + OpNo * NewElts);
5987 if (UseBuildVector) {
5992 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5994 int Idx = Mask[FirstMaskIdx + MaskOffset];
5999 if (
Input >= std::size(Inputs)) {
6006 Idx -=
Input * NewElts;
6010 .buildExtractVectorElement(
6011 EltTy, Inputs[
Input],
6017 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6018 }
else if (InputUsed[0] == -1U) {
6020 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6021 }
else if (NewElts == 1) {
6022 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6024 Register Op0 = Inputs[InputUsed[0]];
6028 : Inputs[InputUsed[1]];
6030 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6037 MI.eraseFromParent();
6050 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6056 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6059 const unsigned NumParts =
6061 : SrcTy.getNumElements();
6065 if (DstTy != NarrowTy)
6071 unsigned NumPartsLeft = NumParts;
6072 while (NumPartsLeft > 1) {
6073 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6076 .buildInstr(ScalarOpc, {NarrowTy},
6077 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
6080 SplitSrcs = PartialResults;
6081 PartialResults.
clear();
6082 NumPartsLeft = SplitSrcs.
size();
6086 MI.eraseFromParent();
6091 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6092 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
6095 MI.eraseFromParent();
6099 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6101 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
6109 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6112 Register Acc = PartialReductions[0];
6113 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6114 if (Part == NumParts - 1) {
6116 {Acc, PartialReductions[Part]});
6119 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
6123 MI.eraseFromParent();
6129 unsigned int TypeIdx,
6131 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6132 MI.getFirst3RegLLTs();
6133 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6137 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6138 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6139 "Unexpected vecreduce opcode");
6140 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6141 ? TargetOpcode::G_FADD
6142 : TargetOpcode::G_FMUL;
6145 unsigned NumParts = SrcTy.getNumElements();
6148 for (
unsigned i = 0; i < NumParts; i++)
6149 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
6153 MI.eraseFromParent();
6160 unsigned ScalarOpc) {
6168 while (SplitSrcs.
size() > 1) {
6170 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6178 SplitSrcs = std::move(PartialRdxs);
6182 MI.getOperand(1).setReg(SplitSrcs[0]);
6189 const LLT HalfTy,
const LLT AmtTy) {
6191 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6192 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6196 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6197 MI.eraseFromParent();
6203 unsigned VTBits = 2 * NVTBits;
6206 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6207 if (Amt.
ugt(VTBits)) {
6209 }
else if (Amt.
ugt(NVTBits)) {
6212 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6213 }
else if (Amt == NVTBits) {
6221 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6224 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6225 if (Amt.
ugt(VTBits)) {
6227 }
else if (Amt.
ugt(NVTBits)) {
6229 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6231 }
else if (Amt == NVTBits) {
6235 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6237 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6239 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6245 if (Amt.
ugt(VTBits)) {
6247 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6248 }
else if (Amt.
ugt(NVTBits)) {
6250 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6252 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6253 }
else if (Amt == NVTBits) {
6256 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6258 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6260 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6262 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6269 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6270 MI.eraseFromParent();
6286 LLT DstTy = MRI.getType(DstReg);
6291 LLT ShiftAmtTy = MRI.getType(Amt);
6293 if (DstEltSize % 2 != 0)
6309 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6320 const unsigned NewBitSize = DstEltSize / 2;
6332 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6334 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6335 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6338 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6339 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6341 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6346 switch (
MI.getOpcode()) {
6347 case TargetOpcode::G_SHL: {
6349 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6351 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6352 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6353 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6356 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6357 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6359 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6361 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6363 ResultRegs[0] =
Lo.getReg(0);
6364 ResultRegs[1] =
Hi.getReg(0);
6367 case TargetOpcode::G_LSHR:
6368 case TargetOpcode::G_ASHR: {
6370 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6372 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6373 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6374 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6378 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6381 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6382 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6384 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6388 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6390 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6392 ResultRegs[0] =
Lo.getReg(0);
6393 ResultRegs[1] =
Hi.getReg(0);
6400 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6401 MI.eraseFromParent();
6410 LLT TargetTy,
LLT ShiftAmtTy) {
6413 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6415 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6416 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6417 const bool NeedsInterWordShift = ShiftBits != 0;
6420 case TargetOpcode::G_SHL: {
6423 if (PartIdx < ShiftWords)
6426 unsigned SrcIdx = PartIdx - ShiftWords;
6427 if (!NeedsInterWordShift)
6428 return SrcParts[SrcIdx];
6433 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6437 return Hi.getReg(0);
6440 case TargetOpcode::G_LSHR: {
6441 unsigned SrcIdx = PartIdx + ShiftWords;
6442 if (SrcIdx >= NumParts)
6444 if (!NeedsInterWordShift)
6445 return SrcParts[SrcIdx];
6449 if (SrcIdx + 1 < NumParts) {
6450 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6454 return Lo.getReg(0);
6457 case TargetOpcode::G_ASHR: {
6459 unsigned SrcIdx = PartIdx + ShiftWords;
6460 if (SrcIdx >= NumParts)
6462 if (!NeedsInterWordShift)
6463 return SrcParts[SrcIdx];
6468 (SrcIdx == NumParts - 1)
6472 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6494 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6495 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6500 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6509 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6510 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6512 auto IsZeroBitShift =
6520 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6521 : TargetOpcode::G_SHL;
6524 auto TargetBitsConst =
6526 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6531 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6536 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6538 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6542 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6555 LLT DstTy = MRI.getType(DstReg);
6559 const unsigned NumParts = DstBits / TargetBits;
6561 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6571 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6572 MI.eraseFromParent();
6577 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6578 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6584 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6588 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6591 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6592 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6596 for (
unsigned I = 0;
I < NumParts; ++
I)
6598 Params, TargetTy, ShiftAmtTy);
6600 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6601 MI.eraseFromParent();
6610 LLT DstTy = MRI.getType(DstReg);
6611 LLT ShiftAmtTy = MRI.getType(AmtReg);
6615 const unsigned NumParts = DstBits / TargetBits;
6617 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6634 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6646 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6647 auto TargetBitsLog2Const =
6648 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6649 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6652 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6654 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6662 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6663 auto TargetBitsMinusOneConst =
6664 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6666 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6667 TargetBitsMinusOneConst)
6670 FillValue = ZeroReg;
6678 for (
unsigned I = 0;
I < NumParts; ++
I) {
6680 Register InBoundsResult = FillValue;
6690 for (
unsigned K = 0; K < NumParts; ++K) {
6691 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6693 WordShift, WordShiftKConst);
6705 switch (
MI.getOpcode()) {
6706 case TargetOpcode::G_SHL:
6707 MainSrcIdx = (int)
I - (
int)K;
6708 CarrySrcIdx = MainSrcIdx - 1;
6710 case TargetOpcode::G_LSHR:
6711 case TargetOpcode::G_ASHR:
6712 MainSrcIdx = (int)
I + (
int)K;
6713 CarrySrcIdx = MainSrcIdx + 1;
6721 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6722 Register MainOp = SrcParts[MainSrcIdx];
6726 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6727 CarryOp = SrcParts[CarrySrcIdx];
6728 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6729 CarrySrcIdx >= (
int)NumParts)
6730 CarryOp = FillValue;
6736 ResultForK = FillValue;
6742 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6749 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6753 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6754 MI.eraseFromParent();
6761 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6764 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6779 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6784 "getNeutralElementForVecReduce called with invalid opcode!");
6785 case TargetOpcode::G_VECREDUCE_ADD:
6786 case TargetOpcode::G_VECREDUCE_OR:
6787 case TargetOpcode::G_VECREDUCE_XOR:
6788 case TargetOpcode::G_VECREDUCE_UMAX:
6790 case TargetOpcode::G_VECREDUCE_MUL:
6792 case TargetOpcode::G_VECREDUCE_AND:
6793 case TargetOpcode::G_VECREDUCE_UMIN:
6796 case TargetOpcode::G_VECREDUCE_SMAX:
6799 case TargetOpcode::G_VECREDUCE_SMIN:
6802 case TargetOpcode::G_VECREDUCE_FADD:
6804 case TargetOpcode::G_VECREDUCE_FMUL:
6806 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6807 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6808 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6809 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6817 unsigned Opc =
MI.getOpcode();
6819 case TargetOpcode::G_IMPLICIT_DEF:
6820 case TargetOpcode::G_LOAD: {
6828 case TargetOpcode::G_STORE:
6835 case TargetOpcode::G_AND:
6836 case TargetOpcode::G_OR:
6837 case TargetOpcode::G_XOR:
6838 case TargetOpcode::G_ADD:
6839 case TargetOpcode::G_SUB:
6840 case TargetOpcode::G_MUL:
6841 case TargetOpcode::G_FADD:
6842 case TargetOpcode::G_FSUB:
6843 case TargetOpcode::G_FMUL:
6844 case TargetOpcode::G_FDIV:
6845 case TargetOpcode::G_FCOPYSIGN:
6846 case TargetOpcode::G_UADDSAT:
6847 case TargetOpcode::G_USUBSAT:
6848 case TargetOpcode::G_SADDSAT:
6849 case TargetOpcode::G_SSUBSAT:
6850 case TargetOpcode::G_SMIN:
6851 case TargetOpcode::G_SMAX:
6852 case TargetOpcode::G_UMIN:
6853 case TargetOpcode::G_UMAX:
6854 case TargetOpcode::G_FMINNUM:
6855 case TargetOpcode::G_FMAXNUM:
6856 case TargetOpcode::G_FMINNUM_IEEE:
6857 case TargetOpcode::G_FMAXNUM_IEEE:
6858 case TargetOpcode::G_FMINIMUM:
6859 case TargetOpcode::G_FMAXIMUM:
6860 case TargetOpcode::G_FMINIMUMNUM:
6861 case TargetOpcode::G_FMAXIMUMNUM:
6862 case TargetOpcode::G_STRICT_FADD:
6863 case TargetOpcode::G_STRICT_FSUB:
6864 case TargetOpcode::G_STRICT_FMUL: {
6872 case TargetOpcode::G_SHL:
6873 case TargetOpcode::G_ASHR:
6874 case TargetOpcode::G_LSHR: {
6880 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6886 case TargetOpcode::G_FMA:
6887 case TargetOpcode::G_STRICT_FMA:
6888 case TargetOpcode::G_FSHR:
6889 case TargetOpcode::G_FSHL: {
6898 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6899 case TargetOpcode::G_EXTRACT:
6906 case TargetOpcode::G_INSERT:
6907 case TargetOpcode::G_INSERT_VECTOR_ELT:
6908 case TargetOpcode::G_FREEZE:
6909 case TargetOpcode::G_FNEG:
6910 case TargetOpcode::G_FABS:
6911 case TargetOpcode::G_FSQRT:
6912 case TargetOpcode::G_FCEIL:
6913 case TargetOpcode::G_FFLOOR:
6914 case TargetOpcode::G_FNEARBYINT:
6915 case TargetOpcode::G_FRINT:
6916 case TargetOpcode::G_INTRINSIC_ROUND:
6917 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6918 case TargetOpcode::G_INTRINSIC_TRUNC:
6919 case TargetOpcode::G_BITREVERSE:
6920 case TargetOpcode::G_BSWAP:
6921 case TargetOpcode::G_FCANONICALIZE:
6922 case TargetOpcode::G_SEXT_INREG:
6923 case TargetOpcode::G_ABS:
6924 case TargetOpcode::G_CTLZ:
6925 case TargetOpcode::G_CTPOP:
6933 case TargetOpcode::G_SELECT: {
6934 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6936 if (!CondTy.isScalar() ||
6942 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6944 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6949 if (CondTy.isVector())
6959 case TargetOpcode::G_UNMERGE_VALUES:
6961 case TargetOpcode::G_PHI:
6963 case TargetOpcode::G_SHUFFLE_VECTOR:
6965 case TargetOpcode::G_BUILD_VECTOR: {
6967 for (
auto Op :
MI.uses()) {
6975 MIRBuilder.buildDeleteTrailingVectorElements(
6976 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6977 MI.eraseFromParent();
6980 case TargetOpcode::G_SEXT:
6981 case TargetOpcode::G_ZEXT:
6982 case TargetOpcode::G_ANYEXT:
6983 case TargetOpcode::G_TRUNC:
6984 case TargetOpcode::G_FPTRUNC:
6985 case TargetOpcode::G_FPEXT:
6986 case TargetOpcode::G_FPTOSI:
6987 case TargetOpcode::G_FPTOUI:
6988 case TargetOpcode::G_FPTOSI_SAT:
6989 case TargetOpcode::G_FPTOUI_SAT:
6990 case TargetOpcode::G_SITOFP:
6991 case TargetOpcode::G_UITOFP: {
6998 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7001 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7009 case TargetOpcode::G_ICMP:
7010 case TargetOpcode::G_FCMP: {
7018 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7023 case TargetOpcode::G_BITCAST: {
7027 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7028 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7044 case TargetOpcode::G_VECREDUCE_FADD:
7045 case TargetOpcode::G_VECREDUCE_FMUL:
7046 case TargetOpcode::G_VECREDUCE_ADD:
7047 case TargetOpcode::G_VECREDUCE_MUL:
7048 case TargetOpcode::G_VECREDUCE_AND:
7049 case TargetOpcode::G_VECREDUCE_OR:
7050 case TargetOpcode::G_VECREDUCE_XOR:
7051 case TargetOpcode::G_VECREDUCE_SMAX:
7052 case TargetOpcode::G_VECREDUCE_SMIN:
7053 case TargetOpcode::G_VECREDUCE_UMAX:
7054 case TargetOpcode::G_VECREDUCE_UMIN: {
7055 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7057 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7058 auto NeutralElement = getNeutralElementForVecReduce(
7064 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7065 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7066 NeutralElement, Idx);
7070 MO.
setReg(NewVec.getReg(0));
7082 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7084 unsigned MaskNumElts = Mask.size();
7085 unsigned SrcNumElts = SrcTy.getNumElements();
7088 if (MaskNumElts == SrcNumElts)
7091 if (MaskNumElts < SrcNumElts) {
7099 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7100 MI.getOperand(1).getReg(),
7101 MI.getOperand(2).getReg(), NewMask);
7102 MI.eraseFromParent();
7107 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7108 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7117 MOps1[0] =
MI.getOperand(1).getReg();
7118 MOps2[0] =
MI.getOperand(2).getReg();
7120 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7121 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7125 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7127 if (Idx >=
static_cast<int>(SrcNumElts))
7128 Idx += PaddedMaskNumElts - SrcNumElts;
7133 if (MaskNumElts != PaddedMaskNumElts) {
7135 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7138 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7140 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7145 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7148 MI.eraseFromParent();
7154 unsigned int TypeIdx,
LLT MoreTy) {
7155 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7157 unsigned NumElts = DstTy.getNumElements();
7160 if (DstTy.isVector() && Src1Ty.isVector() &&
7161 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7169 if (DstTy != Src1Ty || DstTy != Src2Ty)
7177 for (
unsigned I = 0;
I != NumElts; ++
I) {
7179 if (Idx <
static_cast<int>(NumElts))
7182 NewMask[
I] = Idx - NumElts + WidenNumElts;
7186 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7187 MI.getOperand(1).getReg(),
7188 MI.getOperand(2).getReg(), NewMask);
7189 MI.eraseFromParent();
7198 unsigned SrcParts = Src1Regs.
size();
7199 unsigned DstParts = DstRegs.
size();
7201 unsigned DstIdx = 0;
7203 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7204 DstRegs[DstIdx] = FactorSum;
7209 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7211 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7212 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7214 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7220 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7221 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7222 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7223 unsigned i = RevI - 1;
7225 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7235 if (DstIdx != DstParts - 1) {
7236 MachineInstrBuilder Uaddo =
7237 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7238 FactorSum = Uaddo.
getReg(0);
7239 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7240 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7241 MachineInstrBuilder Uaddo =
7242 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7243 FactorSum = Uaddo.
getReg(0);
7244 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7245 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7249 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7250 for (
unsigned i = 2; i < Factors.
size(); ++i)
7251 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7254 CarrySumPrevDstIdx = CarrySum;
7255 DstRegs[DstIdx] = FactorSum;
7267 LLT DstType = MRI.getType(DstReg);
7269 if (DstType.isVector())
7272 unsigned Opcode =
MI.getOpcode();
7273 unsigned OpO, OpE, OpF;
7275 case TargetOpcode::G_SADDO:
7276 case TargetOpcode::G_SADDE:
7277 case TargetOpcode::G_UADDO:
7278 case TargetOpcode::G_UADDE:
7279 case TargetOpcode::G_ADD:
7280 OpO = TargetOpcode::G_UADDO;
7281 OpE = TargetOpcode::G_UADDE;
7282 OpF = TargetOpcode::G_UADDE;
7283 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7284 OpF = TargetOpcode::G_SADDE;
7286 case TargetOpcode::G_SSUBO:
7287 case TargetOpcode::G_SSUBE:
7288 case TargetOpcode::G_USUBO:
7289 case TargetOpcode::G_USUBE:
7290 case TargetOpcode::G_SUB:
7291 OpO = TargetOpcode::G_USUBO;
7292 OpE = TargetOpcode::G_USUBE;
7293 OpF = TargetOpcode::G_USUBE;
7294 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7295 OpF = TargetOpcode::G_SSUBE;
7302 unsigned NumDefs =
MI.getNumExplicitDefs();
7303 Register Src1 =
MI.getOperand(NumDefs).getReg();
7304 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7307 CarryDst =
MI.getOperand(1).getReg();
7308 if (
MI.getNumOperands() == NumDefs + 3)
7309 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7311 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7312 LLT LeftoverTy, DummyTy;
7314 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7319 int NarrowParts = Src1Regs.
size();
7320 Src1Regs.
append(Src1Left);
7321 Src2Regs.
append(Src2Left);
7324 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7326 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7329 if (i == e - 1 && CarryDst)
7330 CarryOut = CarryDst;
7332 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7335 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7336 {Src1Regs[i], Src2Regs[i]});
7337 }
else if (i == e - 1) {
7338 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7339 {Src1Regs[i], Src2Regs[i], CarryIn});
7341 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7342 {Src1Regs[i], Src2Regs[i], CarryIn});
7348 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7349 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7350 ArrayRef(DstRegs).drop_front(NarrowParts));
7352 MI.eraseFromParent();
7358 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7360 LLT Ty = MRI.getType(DstReg);
7364 unsigned Size = Ty.getSizeInBits();
7366 if (
Size % NarrowSize != 0)
7369 unsigned NumParts =
Size / NarrowSize;
7370 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7371 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7377 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7381 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7382 MI.eraseFromParent();
7392 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7395 LLT SrcTy = MRI.getType(Src);
7406 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7419 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7422 if (SizeOp1 % NarrowSize != 0)
7424 int NumParts = SizeOp1 / NarrowSize;
7427 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7431 uint64_t OpStart =
MI.getOperand(2).getImm();
7432 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7433 for (
int i = 0; i < NumParts; ++i) {
7434 unsigned SrcStart = i * NarrowSize;
7436 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7439 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7447 int64_t ExtractOffset;
7449 if (OpStart < SrcStart) {
7451 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7453 ExtractOffset = OpStart - SrcStart;
7454 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7458 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7460 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7461 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7468 if (MRI.getType(DstReg).isVector())
7469 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7470 else if (DstRegs.
size() > 1)
7471 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7474 MI.eraseFromParent();
7486 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7488 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7491 SrcRegs.
append(LeftoverRegs);
7495 uint64_t OpStart =
MI.getOperand(3).getImm();
7496 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7497 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7498 unsigned DstStart =
I * NarrowSize;
7500 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7508 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7510 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7514 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7522 int64_t ExtractOffset, InsertOffset;
7524 if (OpStart < DstStart) {
7526 ExtractOffset = DstStart - OpStart;
7527 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7529 InsertOffset = OpStart - DstStart;
7532 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7536 if (ExtractOffset != 0 || SegSize != OpSize) {
7538 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7539 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7542 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7543 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7551 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7554 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7556 MI.eraseFromParent();
7564 LLT DstTy = MRI.getType(DstReg);
7566 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7572 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7573 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7577 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7578 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7581 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7582 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7583 {Src0Regs[I], Src1Regs[I]});
7587 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7590 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7591 DstLeftoverRegs.
push_back(Inst.getReg(0));
7594 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7595 LeftoverTy, DstLeftoverRegs);
7597 MI.eraseFromParent();
7607 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7609 LLT DstTy = MRI.getType(DstReg);
7614 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7615 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7616 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7618 MI.eraseFromParent();
7628 Register CondReg =
MI.getOperand(1).getReg();
7629 LLT CondTy = MRI.getType(CondReg);
7630 if (CondTy.isVector())
7634 LLT DstTy = MRI.getType(DstReg);
7640 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7641 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7645 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7646 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7649 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7651 CondReg, Src1Regs[
I], Src2Regs[
I]);
7655 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7657 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7661 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7662 LeftoverTy, DstLeftoverRegs);
7664 MI.eraseFromParent();
7674 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7677 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7678 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7681 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7683 auto C_0 =
B.buildConstant(NarrowTy, 0);
7685 UnmergeSrc.getReg(1), C_0);
7686 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7687 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7688 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7689 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7690 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7691 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7693 MI.eraseFromParent();
7706 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7709 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7710 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7713 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7715 auto C_0 =
B.buildConstant(NarrowTy, 0);
7717 UnmergeSrc.getReg(0), C_0);
7718 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7719 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7720 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7721 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7722 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7723 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7725 MI.eraseFromParent();
7738 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7741 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7746 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7750 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7751 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7759 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7760 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7763 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7764 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7766 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7768 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7770 MI.eraseFromParent();
7780 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7783 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7784 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7786 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7787 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7788 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7790 MI.eraseFromParent();
7805 LLT ExpTy = MRI.getType(ExpReg);
7810 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7811 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7812 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7813 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7815 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7817 MI.getOperand(2).setReg(Trunc.getReg(0));
7824 unsigned Opc =
MI.getOpcode();
7827 auto QAction = LI.getAction(Q).Action;
7833 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7836 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7840 case TargetOpcode::G_CTLZ: {
7841 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7842 unsigned Len = SrcTy.getScalarSizeInBits();
7844 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7846 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7847 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7850 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7851 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7852 MI.eraseFromParent();
7868 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7869 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7872 Op = MIBOp.getReg(0);
7877 MI.eraseFromParent();
7880 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7883 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7887 case TargetOpcode::G_CTTZ: {
7888 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7890 unsigned Len = SrcTy.getScalarSizeInBits();
7891 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
7894 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
7895 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7898 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7899 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7900 MI.eraseFromParent();
7907 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7908 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7910 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7911 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7912 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7913 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7916 MI.eraseFromParent();
7920 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7921 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7925 case TargetOpcode::G_CTPOP: {
7927 LLT Ty = MRI.getType(SrcReg);
7928 unsigned Size = Ty.getScalarSizeInBits();
7940 auto C_1 =
B.buildConstant(Ty, 1);
7941 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7943 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7944 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7945 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7949 auto C_2 =
B.buildConstant(Ty, 2);
7950 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7952 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7953 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7954 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7955 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7962 auto C_4 =
B.buildConstant(Ty, 4);
7963 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7964 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7966 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7967 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7969 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
7972 if (
Size == 16 && !Ty.isVector()) {
7974 auto C_8 =
B.buildConstant(Ty, 8);
7975 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
7976 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
7977 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
7978 MI.eraseFromParent();
7987 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7989 auto IsMulSupported = [
this](
const LLT Ty) {
7990 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7993 if (IsMulSupported(Ty)) {
7994 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7995 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7997 auto ResTmp = B8Count;
7998 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7999 auto ShiftC =
B.buildConstant(Ty, Shift);
8000 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8001 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8003 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8005 MI.eraseFromParent();
8008 case TargetOpcode::G_CTLS: {
8009 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8013 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8014 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8016 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8022 MI.eraseFromParent();
8043 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8044 LLT Ty = MRI.getType(Dst);
8045 LLT ShTy = MRI.getType(Z);
8052 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8053 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8058 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8059 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8063 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8076 MI.eraseFromParent();
8082 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8083 LLT Ty = MRI.getType(Dst);
8084 LLT ShTy = MRI.getType(Z);
8087 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8097 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8098 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8099 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8100 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8101 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8105 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8108 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8111 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8113 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8114 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8115 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8118 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8120 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8122 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8125 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8126 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8131 MI.eraseFromParent();
8142 LLT Ty = MRI.getType(Dst);
8143 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8145 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8146 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8149 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8150 return lowerFunnelShiftAsShifts(
MI);
8154 if (Result == UnableToLegalize)
8155 return lowerFunnelShiftAsShifts(
MI);
8160 auto [Dst, Src] =
MI.getFirst2Regs();
8161 LLT DstTy = MRI.getType(Dst);
8162 LLT SrcTy = MRI.getType(Src);
8166 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8174 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8178 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8182 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8187 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8188 {UnmergeSrc.getReg(0)});
8189 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8190 {UnmergeSrc.getReg(1)});
8193 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8195 MI.eraseFromParent();
8212 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8216 LLT DstTy = MRI.getType(DstReg);
8217 LLT SrcTy = MRI.getType(SrcReg);
8225 SrcTy.getElementCount().divideCoefficientBy(2));
8238 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8250 MI.eraseFromParent();
8259 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8260 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8261 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8262 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8263 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8264 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8265 MI.eraseFromParent();
8270 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8272 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8273 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8278 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8279 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8281 return lowerRotateWithReverseRotate(
MI);
8284 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8285 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8286 bool IsFShLegal =
false;
8287 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8288 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8292 MI.eraseFromParent();
8297 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8300 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8305 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8306 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8307 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8313 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8314 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8316 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8322 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8323 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8325 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8327 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8332 MI.eraseFromParent();
8340 auto [Dst, Src] =
MI.getFirst2Regs();
8345 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8373 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8386 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8390 MI.eraseFromParent();
8398 auto [Dst, Src] =
MI.getFirst2Regs();
8403 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8416 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8418 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8423 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8425 MI.eraseFromParent();
8433 auto [Dst, Src] =
MI.getFirst2Regs();
8437 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8448 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8449 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8451 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8458 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8459 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8460 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8462 MI.eraseFromParent();
8473 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8474 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8480 MI.eraseFromParent();
8485 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8488 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8489 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8490 MIRBuilder.buildSelect(Dst, Src, True, False);
8491 MI.eraseFromParent();
8495 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8515 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8522 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8523 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8524 MIRBuilder.buildSelect(Dst, Src, True, False);
8525 MI.eraseFromParent();
8529 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8535 if (DstTy.getScalarSizeInBits() == 32) {
8542 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8543 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8545 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8552 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8553 MI.eraseFromParent();
8561 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8565 if (SrcTy !=
S64 && SrcTy !=
S32)
8567 if (DstTy !=
S32 && DstTy !=
S64)
8594 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8596 MI.eraseFromParent();
8601 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8606 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8613 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8615 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8616 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8618 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8619 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8621 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8623 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8624 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8625 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8628 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8629 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8630 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8632 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8635 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8640 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8641 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8647 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8649 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8650 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8652 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8657 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8658 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8660 MI.eraseFromParent();
8666 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8668 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8669 unsigned SatWidth = DstTy.getScalarSizeInBits();
8673 APInt MinInt, MaxInt;
8696 if (AreExactFloatBounds) {
8698 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8701 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8703 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8712 MI.eraseFromParent();
8717 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8722 MI.eraseFromParent();
8729 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8737 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8747 MI.eraseFromParent();
8753 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8757 MI.eraseFromParent();
8764 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8765 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8766 "Only G_FPEXT and G_FPTRUNC are expected");
8768 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8773 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8775 StoreOpc = TargetOpcode::G_STORE;
8776 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8779 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8780 LoadOpc = TargetOpcode::G_LOAD;
8789 StackTy, StackTyAlign);
8790 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8793 StackTy, StackTyAlign);
8794 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8796 MI.eraseFromParent();
8804 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8805 assert(SrcTy.getScalarType().isBFloat16() &&
8806 "expected a bf16 source for bf16 fpext lowering");
8817 if (DstTy.getScalarType().isFloat32())
8822 MI.eraseFromParent();
8827 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8828 if (SrcTy.getScalarType().isBFloat16() &&
8829 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8841 auto [Dst, Src] =
MI.getFirst2Regs();
8845 if (MRI.getType(Src).isVector())
8849 unsigned Flags =
MI.getFlags();
8852 MI.eraseFromParent();
8856 const unsigned ExpMask = 0x7ff;
8857 const unsigned ExpBiasf64 = 1023;
8858 const unsigned ExpBiasf16 = 15;
8860 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8870 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8877 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8879 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8881 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8885 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8887 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8889 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8890 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8898 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8899 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
8910 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
8921 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
8937 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
8947 MI.eraseFromParent();
8954 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8962 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
8988 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
8990 MI.eraseFromParent();
8999 LLT OperandTy = MRI.getType(
Op);
9009 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9011 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9012 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9013 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9014 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9015 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9023 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9026 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9028 AbsWide, AbsNarrowAsWide);
9032 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9033 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9035 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9036 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9042 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9048 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9049 MI.eraseFromParent();
9055 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9056 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9059 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9062 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9069 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9070 LLT Ty = MRI.getType(Dst);
9072 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9073 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9074 MI.eraseFromParent();
9079 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9080 LLT Ty = MRI.getType(Src);
9081 auto Flags =
MI.getFlags();
9089 FracToUse = FracPart.getReg(0);
9091 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9095 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9097 FracToUse =
Select.getReg(0);
9100 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9103 MI.eraseFromParent();
9109 case TargetOpcode::G_SMIN:
9111 case TargetOpcode::G_SMAX:
9113 case TargetOpcode::G_UMIN:
9115 case TargetOpcode::G_UMAX:
9123 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9128 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9129 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9131 MI.eraseFromParent();
9140 LLT DstTy = MRI.getType(Dst);
9141 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9151 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9152 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9154 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9157 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9158 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9159 if (TLI.preferSelectsOverBooleanArithmetic(
9162 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9163 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9165 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9166 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9172 unsigned BoolExtOp =
9174 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9175 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9179 MI.eraseFromParent();
9185 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9186 const int Src0Size = Src0Ty.getScalarSizeInBits();
9187 const int Src1Size = Src1Ty.getScalarSizeInBits();
9197 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9198 Src0Ty.getScalarType().isInteger()))
9199 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9201 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9202 Src1Ty.getScalarType().isInteger()))
9203 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9208 auto NotSignBitMask =
MIRBuilder.buildConstant(
9212 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9214 if (Src0Ty == Src1Ty) {
9215 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9216 }
else if (Src0Size > Src1Size) {
9217 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9218 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9219 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9220 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
9222 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9223 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9224 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9225 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9231 unsigned Flags =
MI.getFlags();
9236 if (DstTy == DstIntTy)
9237 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9243 MI.eraseFromParent();
9254 switch (
MI.getOpcode()) {
9255 case TargetOpcode::G_FMINNUM:
9256 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9258 case TargetOpcode::G_FMINIMUMNUM:
9259 NewOp = TargetOpcode::G_FMINNUM;
9261 case TargetOpcode::G_FMAXNUM:
9262 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9264 case TargetOpcode::G_FMAXIMUMNUM:
9265 NewOp = TargetOpcode::G_FMAXNUM;
9271 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9272 LLT Ty = MRI.getType(Dst);
9281 if (!VT->isKnownNeverSNaN(Src0))
9282 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9284 if (!VT->isKnownNeverSNaN(Src1))
9285 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9290 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9291 MI.eraseFromParent();
9297 unsigned Opc =
MI.getOpcode();
9298 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9299 LLT Ty = MRI.getType(Dst);
9302 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9304 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9305 unsigned OpcNonIeee =
9306 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9307 bool MinMaxMustRespectOrderedZero =
false;
9311 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9313 MinMaxMustRespectOrderedZero =
true;
9314 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9319 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9324 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9327 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9331 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9333 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9343 const unsigned Flags =
MI.getFlags();
9349 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9351 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9353 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9355 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9357 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9362 MI.eraseFromParent();
9369 LLT Ty = MRI.getType(DstReg);
9370 unsigned Flags =
MI.getFlags();
9375 MI.eraseFromParent();
9381 auto [DstReg,
X] =
MI.getFirst2Regs();
9382 const unsigned Flags =
MI.getFlags();
9383 const LLT Ty = MRI.getType(DstReg);
9395 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9397 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9402 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9403 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9404 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9405 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9407 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9409 MI.eraseFromParent();
9414 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9415 unsigned Flags =
MI.getFlags();
9416 LLT Ty = MRI.getType(DstReg);
9423 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9424 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9427 SrcReg, Zero, Flags);
9429 SrcReg, Trunc, Flags);
9433 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9434 MI.eraseFromParent();
9440 const unsigned NumOps =
MI.getNumOperands();
9441 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9442 unsigned PartSize = Src0Ty.getSizeInBits();
9447 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9448 const unsigned Offset = (
I - 1) * PartSize;
9451 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9454 MRI.createGenericVirtualRegister(WideTy);
9457 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9458 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9459 ResultReg = NextResult;
9462 if (DstTy.isPointer()) {
9463 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9464 DstTy.getAddressSpace())) {
9470 }
else if (WideTy != DstTy) {
9474 MI.eraseFromParent();
9480 const unsigned NumDst =
MI.getNumOperands() - 1;
9481 Register SrcReg =
MI.getOperand(NumDst).getReg();
9482 Register Dst0Reg =
MI.getOperand(0).getReg();
9483 LLT DstTy = MRI.getType(Dst0Reg);
9492 LLT IntTy = MRI.getType(SrcReg);
9497 unsigned Offset = DstSize;
9498 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9500 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9504 MI.eraseFromParent();
9523 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9524 InsertVal =
MI.getOperand(2).getReg();
9526 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9528 LLT VecTy = MRI.getType(SrcVec);
9538 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9539 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9541 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9544 MI.eraseFromParent();
9549 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9560 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9567 int64_t
Offset = IdxVal * EltBytes;
9578 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9581 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9583 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9586 MI.eraseFromParent();
9592 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9593 MI.getFirst3RegLLTs();
9603 for (
int Idx : Mask) {
9605 if (!
Undef.isValid())
9611 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9613 int NumElts = Src0Ty.getNumElements();
9614 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9615 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9616 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9618 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9620 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9625 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9626 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9627 MI.eraseFromParent();
9633 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9634 MI.getFirst4RegLLTs();
9636 if (VecTy.isScalableVector())
9652 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9655 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9658 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9661 std::optional<APInt> PassthruSplatVal =
9664 if (PassthruSplatVal.has_value()) {
9666 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9667 }
else if (HasPassthru) {
9668 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9669 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9675 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9679 unsigned NumElmts = VecTy.getNumElements();
9680 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9682 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9685 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9688 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9693 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9695 if (HasPassthru &&
I == NumElmts - 1) {
9698 auto AllLanesSelected =
MIRBuilder.buildICmp(
9700 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9701 {OutPos, EndOfVector});
9705 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9707 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9712 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9714 MI.eraseFromParent();
9731 if (Alignment >
Align(1)) {
9743 const auto &MF = *
MI.getMF();
9749 Register AllocSize =
MI.getOperand(1).getReg();
9752 LLT PtrTy = MRI.getType(Dst);
9753 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9760 MI.eraseFromParent();
9766 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9771 MI.eraseFromParent();
9777 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9782 MI.eraseFromParent();
9788 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9789 unsigned Offset =
MI.getOperand(2).getImm();
9792 if (SrcTy.isVector()) {
9793 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9794 unsigned DstSize = DstTy.getSizeInBits();
9796 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9797 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9799 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9803 for (
unsigned Idx =
Offset / SrcEltSize;
9804 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9805 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9807 if (SubVectorElts.
size() == 1)
9808 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9810 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9812 MI.eraseFromParent();
9818 if ((SrcTy.isPointer() &&
9819 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9820 (DstTy.isPointer() &&
9821 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9822 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9826 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9827 (SrcTy.isScalar() || SrcTy.isPointer() ||
9828 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9829 LLT SrcIntTy = SrcTy;
9830 if (!SrcTy.isScalar()) {
9832 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9836 if (DstTy.isPointer())
9838 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9844 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9848 if (DstTy.isPointer())
9851 MI.eraseFromParent();
9859 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9862 LLT DstTy = MRI.getType(Src);
9863 LLT InsertTy = MRI.getType(InsertSrc);
9866 bool IsNonIntegralInsert =
9876 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9877 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9884 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9886 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9890 for (; Idx <
Offset / EltSize; ++Idx) {
9891 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9896 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9897 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9899 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9903 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
9905 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
9912 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9915 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9916 MI.eraseFromParent();
9925 if (IsNonIntegralDst || IsNonIntegralInsert) {
9926 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9930 LLT IntDstTy = DstTy;
9934 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9939 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9945 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9951 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9952 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9953 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9956 MI.eraseFromParent();
9962 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9963 MI.getFirst4RegLLTs();
9964 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9967 LLT BoolTy = Dst1Ty;
9969 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9984 auto ResultLowerThanLHS =
9988 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
9992 auto LHSLessThanRHS =
9994 auto ResultNegative =
9996 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10000 MI.eraseFromParent();
10006 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10007 const LLT Ty = MRI.getType(Res);
10010 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10011 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10012 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10016 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10017 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10020 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10023 MI.eraseFromParent();
10028 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10029 const LLT Ty = MRI.getType(Res);
10032 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10033 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10034 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10038 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10039 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10041 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10044 MI.eraseFromParent();
10050 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10051 LLT Ty = MRI.getType(Res);
10055 switch (
MI.getOpcode()) {
10058 case TargetOpcode::G_UADDSAT:
10061 BaseOp = TargetOpcode::G_ADD;
10063 case TargetOpcode::G_SADDSAT:
10066 BaseOp = TargetOpcode::G_ADD;
10068 case TargetOpcode::G_USUBSAT:
10071 BaseOp = TargetOpcode::G_SUB;
10073 case TargetOpcode::G_SSUBSAT:
10076 BaseOp = TargetOpcode::G_SUB;
10091 uint64_t NumBits = Ty.getScalarSizeInBits();
10098 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10102 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10110 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10115 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10116 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10119 MI.eraseFromParent();
10125 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10126 LLT Ty = MRI.getType(Res);
10130 unsigned OverflowOp;
10131 switch (
MI.getOpcode()) {
10134 case TargetOpcode::G_UADDSAT:
10137 OverflowOp = TargetOpcode::G_UADDO;
10139 case TargetOpcode::G_SADDSAT:
10142 OverflowOp = TargetOpcode::G_SADDO;
10144 case TargetOpcode::G_USUBSAT:
10147 OverflowOp = TargetOpcode::G_USUBO;
10149 case TargetOpcode::G_SSUBSAT:
10152 OverflowOp = TargetOpcode::G_SSUBO;
10157 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10158 Register Tmp = OverflowRes.getReg(0);
10159 Register Ov = OverflowRes.getReg(1);
10168 uint64_t NumBits = Ty.getScalarSizeInBits();
10169 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10170 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10173 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10181 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10183 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10185 MI.eraseFromParent();
10191 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10192 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10193 "Expected shlsat opcode!");
10194 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10195 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10196 LLT Ty = MRI.getType(Res);
10200 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10201 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10210 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10215 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10217 MI.eraseFromParent();
10222 auto [Dst, Src] =
MI.getFirst2Regs();
10223 const LLT Ty = MRI.getType(Src);
10224 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10225 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10228 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10229 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10230 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10231 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10234 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10237 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10238 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10240 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10241 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10242 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10244 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10245 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10246 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10248 Res.getInstr()->getOperand(0).setReg(Dst);
10250 MI.eraseFromParent();
10257 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10260 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10261 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10262 return B.buildOr(Dst,
LHS,
RHS);
10267 auto [Dst, Src] =
MI.getFirst2Regs();
10268 const LLT SrcTy = MRI.getType(Src);
10269 unsigned Size = SrcTy.getScalarSizeInBits();
10270 unsigned VSize = SrcTy.getSizeInBits();
10273 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10274 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10275 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10276 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10281 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10282 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10283 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10287 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10310 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10314 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10317 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10321 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10325 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10330 MI.eraseFromParent();
10338 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10339 int NameOpIdx = IsRead ? 1 : 0;
10340 int ValRegIndex = IsRead ? 0 : 1;
10342 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10343 const LLT Ty = MRI.getType(ValReg);
10345 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10352 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10353 Fn,
MI.getDebugLoc()));
10357 MI.eraseFromParent();
10366 MI.eraseFromParent();
10372 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10373 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10374 Register Result =
MI.getOperand(0).getReg();
10375 LLT OrigTy = MRI.getType(Result);
10379 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10380 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10382 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10384 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10385 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10388 MI.eraseFromParent();
10394 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10399 MI.eraseFromParent();
10404 MI.eraseFromParent();
10411 unsigned BitSize = SrcTy.getScalarSizeInBits();
10415 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10422 APInt ExpMask = Inf;
10424 APInt QNaNBitMask =
10428 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10429 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10430 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10431 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10432 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10434 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10438 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10440 LLT DstTyCopy = DstTy;
10442 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10470 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10473 Mask &= ~PartialCheck;
10482 else if (PartialCheck ==
fcZero)
10494 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10495 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10496 auto SubnormalRes =
10498 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10500 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10501 appendToRes(SubnormalRes);
10508 else if (PartialCheck ==
fcInf)
10513 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10520 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10521 if (PartialCheck ==
fcNan) {
10525 }
else if (PartialCheck ==
fcQNan) {
10535 Abs, InfWithQnanBitC);
10536 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10543 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10545 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10546 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10549 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10551 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10554 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10555 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10557 appendToRes(NormalRes);
10561 MI.eraseFromParent();
10567 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10568 MI.getFirst4RegLLTs();
10577 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10578 Op1Ty = MRI.getType(Op1Reg);
10579 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10580 Op2Ty = MRI.getType(Op2Reg);
10584 if (MaskTy.isScalar()) {
10592 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10595 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10597 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10599 if (DstTy.isVector()) {
10601 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10602 MaskReg = ShufSplat.getReg(0);
10606 }
else if (!DstTy.isVector()) {
10611 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10615 if (!Op1Ty.getScalarType().isAnyScalar() &&
10616 !Op1Ty.getScalarType().isInteger())
10617 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10619 if (!Op2Ty.getScalarType().isAnyScalar() &&
10620 !Op2Ty.getScalarType().isInteger()) {
10622 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10623 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10626 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10627 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10628 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10633 if (DstTy == Op1TyInt)
10636 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10640 MI.eraseFromParent();
10646 unsigned Opcode =
MI.getOpcode();
10649 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10650 : TargetOpcode::G_UDIV,
10651 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10653 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10654 : TargetOpcode::G_UREM,
10655 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10656 MI.eraseFromParent();
10666 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10670 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10673 MI.eraseFromParent();
10683 Register SrcReg =
MI.getOperand(1).getReg();
10684 LLT Ty = MRI.getType(SrcReg);
10685 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10688 MI.eraseFromParent();
10694 Register SrcReg =
MI.getOperand(1).getReg();
10695 Register DestReg =
MI.getOperand(0).getReg();
10697 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10698 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10701 MI.eraseFromParent();
10707 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10708 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10709 "Expected G_ABDS or G_ABDU instruction");
10711 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10712 LLT Ty = MRI.getType(LHS);
10722 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10724 MI.eraseFromParent();
10730 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10731 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10732 "Expected G_ABDS or G_ABDU instruction");
10734 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10735 LLT Ty = MRI.getType(LHS);
10740 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10741 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10742 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10744 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10745 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10747 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10749 MI.eraseFromParent();
10754 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10759 if (!(SrcTy.getScalarType().isAnyScalar() ||
10760 SrcTy.getScalarType().isInteger())) {
10762 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10763 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10766 if (MRI.getType(DstReg) != TyInt) {
10770 .buildAnd(TyInt, CastedSrc,
10773 DstTy.getScalarSizeInBits())))
10785 MI.eraseFromParent();
10791 Register SrcReg =
MI.getOperand(1).getReg();
10792 LLT SrcTy = MRI.getType(SrcReg);
10793 LLT DstTy = MRI.getType(SrcReg);
10796 if (SrcTy.isScalar()) {
10801 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10812 Register ListPtr =
MI.getOperand(1).getReg();
10813 LLT PtrTy = MRI.getType(ListPtr);
10820 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10822 const Align A(
MI.getOperand(2).getImm());
10824 if (
A > TLI.getMinStackArgumentAlignment()) {
10826 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10827 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10828 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10829 VAList = AndDst.getReg(0);
10836 LLT LLTTy = MRI.getType(Dst);
10839 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10840 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10845 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10847 Align EltAlignment =
DL.getABITypeAlign(Ty);
10850 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10852 MI.eraseFromParent();
10857 [[maybe_unused]]
unsigned OpCode =
MI.getOpcode();
10858 assert((OpCode == TargetOpcode::G_SMULFIX ||
10859 OpCode == TargetOpcode::G_UMULFIX) &&
10860 "Operator must be either G_SMULFIX or G_UMULFIX!");
10861 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10862 LLT Ty = MRI.getType(Dst);
10863 unsigned Scale =
MI.getOperand(3).getImm();
10867 MI.eraseFromParent();
10873 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
10875 if (
MI.getOpcode() == TargetOpcode::G_SMULFIX) {
10884 if (
MI.getOpcode() == TargetOpcode::G_SMULFIX)
10891 MI.eraseFromParent();
10898 unsigned NumBits = Ty.getScalarSizeInBits();
10900 if (!Ty.isVector() && ValVRegAndVal) {
10901 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10909 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10930 uint64_t KnownLen,
Align Alignment,
10932 auto &MF = *
MI.getParent()->getParent();
10937 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10938 assert(!MemOps.
empty() &&
"Expected at least one memory op");
10941 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10942 const auto &DstMMO = **
MI.memoperands_begin();
10944 if (DstAlignCanChange) {
10947 Align NewAlign =
DL.getABITypeAlign(IRTy);
10948 if (NewAlign > Alignment) {
10949 Alignment = NewAlign;
10957 MachineIRBuilder MIB(
MI);
10959 LLT LargestTy = MemOps[0];
10960 for (
unsigned i = 1; i < MemOps.
size(); i++)
10962 LargestTy = MemOps[i];
10974 LLT PtrTy = MRI.getType(Dst);
10975 unsigned DstOff = 0;
10976 unsigned Size = KnownLen;
10977 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
10978 LLT Ty = MemOps[
I];
10981 if (TySize >
Size) {
10985 DstOff -= TySize -
Size;
10995 TLI.isTruncateFree(LargestVT, VT))
10996 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11009 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11012 MIB.buildStore(
Value, Ptr, *StoreMMO);
11017 MI.eraseFromParent();
11023 uint64_t KnownLen,
Align Alignment,
11025 auto &MF = *
MI.getParent()->getParent();
11029 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11030 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11033 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11039 const auto &DstMMO = **
MI.memoperands_begin();
11040 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11042 if (DstAlignCanChange) {
11045 Align NewAlign =
DL.getABITypeAlign(IRTy);
11050 if (!
TRI->hasStackRealignment(MF))
11051 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11052 NewAlign = std::min(NewAlign, *StackAlign);
11054 if (NewAlign > Alignment) {
11055 Alignment = NewAlign;
11063 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11065 MachineIRBuilder MIB(
MI);
11071 unsigned CurrOffset = 0;
11072 unsigned Size = KnownLen;
11073 for (
auto CopyTy : MemOps) {
11074 TypeSize TySize = CopyTy.getSizeInBytes();
11078 if (TySize >
Size) {
11079 unsigned Overlap = TySize -
Size;
11080 assert(Overlap < CurrOffset &&
11081 "overlapping memcpy load/store spans the whole region or more");
11082 CurrOffset -= Overlap;
11092 if (CurrOffset != 0) {
11093 LLT SrcTy = MRI.getType(Src);
11097 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11099 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11103 if (CurrOffset != 0) {
11104 LLT DstTy = MRI.getType(Dst);
11105 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11107 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11108 CurrOffset += TySize;
11112 MI.eraseFromParent();
11118 uint64_t KnownLen,
Align Alignment,
11120 auto &MF = *
MI.getParent()->getParent();
11124 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11125 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11128 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11129 const auto &DstMMO = **
MI.memoperands_begin();
11130 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11132 if (DstAlignCanChange) {
11135 Align NewAlign =
DL.getABITypeAlign(IRTy);
11140 if (!
TRI->hasStackRealignment(MF))
11141 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11142 NewAlign = std::min(NewAlign, *StackAlign);
11144 if (NewAlign > Alignment) {
11145 Alignment = NewAlign;
11153 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11155 MachineIRBuilder MIB(
MI);
11159 unsigned CurrOffset = 0;
11160 unsigned Size = KnownLen;
11161 SmallVector<Register, 16> LoadVals;
11162 for (
auto CopyTy : MemOps) {
11163 TypeSize TySize = CopyTy.getSizeInBytes();
11167 if (TySize >
Size) {
11168 unsigned Overlap = TySize -
Size;
11169 assert(Overlap < CurrOffset &&
11170 "overlapping memmove load spans the whole region or more");
11171 CurrOffset -= Overlap;
11179 if (CurrOffset != 0) {
11180 LLT SrcTy = MRI.getType(Src);
11183 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11185 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11186 CurrOffset += TySize;
11192 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11193 LLT CopyTy = MemOps[
I];
11198 if (TySize >
Size) {
11199 unsigned Overlap = TySize -
Size;
11200 assert(Overlap < CurrOffset &&
11201 "overlapping memmove store spans the whole region or more");
11202 CurrOffset -= Overlap;
11209 if (CurrOffset != 0) {
11210 LLT DstTy = MRI.getType(Dst);
11213 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11215 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11216 CurrOffset += TySize;
11219 MI.eraseFromParent();
11226 const unsigned Opc =
MI.getOpcode();
11227 assert((
Opc == TargetOpcode::G_MEMCPY ||
11228 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11229 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11230 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11231 "Expected memcpy like instruction");
11233 if (KnownLen == 0) {
11234 MI.eraseFromParent();
11238 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11239 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11242 if (
Opc == TargetOpcode::G_MEMMOVE)
11243 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11245 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11246 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11256 bool DstAlignCanChange;
11257 std::vector<LLT> MemOps;
11259 DstAlignCanChange, MemOps))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static RTLIB::Libcall getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI)
static std::pair< int, int > getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy)
Try to break down OrigTy into NarrowTy sized pieces.
static bool hasSameNumEltsOnAllVectorOperands(GenericMachineInstr &MI, MachineRegisterInfo &MRI, std::initializer_list< unsigned > NonVecOpIndices)
Check that all vector operands have same number of elements.
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg, LLT VecTy)
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, Type *FromType)
static void getUnmergeResults(SmallVectorImpl< Register > &Regs, const MachineInstr &MI)
Append the result registers of G_UNMERGE_VALUES MI to Regs.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
#define RTLIBCASE(LibcallPrefix)
static Type * getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Tracks DebugLocs between checkpoints and verifies that they are transferred.
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmTowardZero
static const fltSemantics & IEEEdouble()
static constexpr roundingMode rmNearestTiesToEven
opStatus
IEEE-754R 7: Default exception handling.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
APInt bitcastToAPInt() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
void negate()
Negate this APInt in place.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, unsigned hiBit)
Wrap version of getBitsSet.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
LLT getLLTTy(const MachineRegisterInfo &MRI) const
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Register getValueReg() const
Get the stored value register.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Represents a insert subvector.
Register getSubVec() const
Register getBigVec() const
uint64_t getIndexImm() const
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
Represents a threeway compare.
A base class for all GenericMachineInstrs.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr ElementCount getElementCount() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
constexpr LLT changeVectorElementType(LLT NewEltTy) const
Returns a vector with the same number of elements but the new element type.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLT changeVectorElementCount(ElementCount EC) const
Return a vector with the same element type and the new element count.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
static LLT floatIEEE(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerThreewayCompare(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI)
LLVM_ABI LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI)
Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
LLVM_ABI LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty)
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSSUBE(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerSMULH_UMULH(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerLoad(GAnyLoad &MI)
LLVM_ABI LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerAbsToAddXor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPEXT_BF16(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizerHelper::LegalizeResult createAtomicLibcall(MachineInstr &MI) const
LLVM_ABI LegalizeResult lowerFConstant(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerBitreverse(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
Legalize a vector instruction by increasing the number of vector elements involved and ignoring the a...
LLVM_ABI LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTLS(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy)
Multi-way shift legalization: directly split wide shifts into target-sized parts in a single step,...
LLVM_ABI Register lowerRoundInexactToOdd(LLT ResultTy, Register Op)
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 lowerFPTRUNC_F64_TO_BF16(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult fewerElementsVectorSeqReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize, Align Alignment, LLT PtrTy)
LLVM_ABI LegalizeResult lowerFPTOSI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerUITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerShuffleVector(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerMergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult createMemLibcall(MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver) const
Create a libcall to memcpy et al.
LLVM_ABI LegalizeResult lowerVECTOR_COMPRESS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMulfix(MachineInstr &MI)
LLVM_ABI void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by producing a vector with und...
LLVM_ABI LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF32WithSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult createLibcall(const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr) const
Helper function that creates a libcall to the given Name using the given calling convention CC.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI void widenScalarDstUsingFPTrunc(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI LegalizeResult lowerTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBswap(MachineInstr &MI)
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
LLVM_ABI LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const
Return the alignment to use for a stack temporary object with the given type.
LLVM_ABI LegalizeResult lowerConstant(MachineInstr &MI)
LLVM_ABI Register coerceToInteger(Register Val)
Cast the given value to an LLT::integer with an equivalent size.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LLVM_ABI LegalizeResult simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver) const
LLVM_ABI LegalizeResult legalizeInstrStep(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Replace MI by a sequence of legal instructions that can implement the same operation.
LLVM_ABI LegalizeResult lowerFMinimumMaximum(MachineInstr &MI)
Tracks which library functions to use for a particular subtarget.
TypeSize getValue() const
void checkpoint(bool CheckDebugLocs=true)
Call this to indicate that it's a good point to assess whether locations have been lost.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
LLVM_ABI StringRef getString() const
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
LLVM_ABI iterator getFirstTerminatorForward()
Finds the first terminator in a block by scanning forward.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
Helper class to build MachineInstr.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_UREM Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0)
Build and insert integer negation Zero = G_CONSTANT 0 Res = G_SUB Zero, Op0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_UITOFP Src0.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object 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.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(Register Def, const MachineRegisterInfo &MRI)
Determines if Def defines a constant integer or a splat vector of constant integers.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
LLVM_ABI bool canLowerMemCpyFamily(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned MaxLen, Register &Dst, Register &Src, uint64_t &KnownLen, Align &Alignment, bool &DstAlignCanChange, std::vector< LLT > &MemOps)
Matcher for memcpy-like instructions.
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
bool isKnownNeverZero() const
Return true if it's known this can never be a zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.