43#define DEBUG_TYPE "legalizer"
56static std::pair<int, int>
62 unsigned NumParts =
Size / NarrowSize;
63 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
66 if (LeftoverSize == 0)
71 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
127 auto Step = LI.getAction(
MI, MRI);
128 switch (Step.Action) {
143 return bitcast(
MI, Step.TypeIdx, Step.NewType);
146 return lower(
MI, Step.TypeIdx, Step.NewType);
155 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
163void LegalizerHelper::insertParts(
Register DstReg,
185 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
187 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
188 return mergeMixedSubvectors(DstReg, AllRegs);
194 extractGCDType(GCDRegs, GCDTy, PartReg);
195 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
196 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
201 LLT Ty = MRI.getType(
Reg);
209void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
212 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
213 appendVectorElts(AllElts, PartRegs[i]);
216 if (!MRI.getType(Leftover).isVector())
219 appendVectorElts(AllElts, Leftover);
221 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
227 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
229 const int StartIdx = Regs.
size();
230 const int NumResults =
MI.getNumOperands() - 1;
232 for (
int I = 0;
I != NumResults; ++
I)
233 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
238 LLT SrcTy = MRI.getType(SrcReg);
239 if (SrcTy == GCDTy) {
245 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
252 LLT SrcTy = MRI.getType(SrcReg);
254 extractGCDType(Parts, GCDTy, SrcReg);
258LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
260 unsigned PadStrategy) {
265 int NumOrigSrc = VRegs.
size();
271 if (NumOrigSrc < NumParts * NumSubParts) {
272 if (PadStrategy == TargetOpcode::G_ZEXT)
273 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
274 else if (PadStrategy == TargetOpcode::G_ANYEXT)
275 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
277 assert(PadStrategy == TargetOpcode::G_SEXT);
282 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
298 for (
int I = 0;
I != NumParts; ++
I) {
299 bool AllMergePartsArePadding =
true;
302 for (
int J = 0; J != NumSubParts; ++J) {
303 int Idx =
I * NumSubParts + J;
304 if (Idx >= NumOrigSrc) {
305 SubMerge[J] = PadReg;
309 SubMerge[J] = VRegs[Idx];
312 AllMergePartsArePadding =
false;
318 if (AllMergePartsArePadding && !AllPadReg) {
319 if (PadStrategy == TargetOpcode::G_ANYEXT)
320 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
321 else if (PadStrategy == TargetOpcode::G_ZEXT)
322 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
331 Remerge[
I] = AllPadReg;
335 if (NumSubParts == 1)
336 Remerge[
I] = SubMerge[0];
338 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
341 if (AllMergePartsArePadding && !AllPadReg)
342 AllPadReg = Remerge[
I];
345 VRegs = std::move(Remerge);
349void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
351 LLT DstTy = MRI.getType(DstReg);
356 if (DstTy == LCMTy) {
357 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
361 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
370 UnmergeDefs[0] = DstReg;
371 for (
unsigned I = 1;
I != NumDefs; ++
I)
372 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
375 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
383#define RTLIBCASE_INT(LibcallPrefix) \
387 return RTLIB::LibcallPrefix##32; \
389 return RTLIB::LibcallPrefix##64; \
391 return RTLIB::LibcallPrefix##128; \
393 llvm_unreachable("unexpected size"); \
397#define RTLIBCASE(LibcallPrefix) \
401 return RTLIB::LibcallPrefix##32; \
403 return RTLIB::LibcallPrefix##64; \
405 return RTLIB::LibcallPrefix##80; \
407 return RTLIB::LibcallPrefix##128; \
409 llvm_unreachable("unexpected size"); \
414 case TargetOpcode::G_LROUND:
416 case TargetOpcode::G_LLROUND:
418 case TargetOpcode::G_MUL:
420 case TargetOpcode::G_SDIV:
422 case TargetOpcode::G_UDIV:
424 case TargetOpcode::G_SREM:
426 case TargetOpcode::G_UREM:
428 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
430 case TargetOpcode::G_FADD:
432 case TargetOpcode::G_FSUB:
434 case TargetOpcode::G_FMUL:
436 case TargetOpcode::G_FDIV:
438 case TargetOpcode::G_FEXP:
440 case TargetOpcode::G_FEXP2:
442 case TargetOpcode::G_FEXP10:
444 case TargetOpcode::G_FREM:
446 case TargetOpcode::G_FPOW:
448 case TargetOpcode::G_FPOWI:
450 case TargetOpcode::G_FMA:
452 case TargetOpcode::G_FSIN:
454 case TargetOpcode::G_FCOS:
456 case TargetOpcode::G_FTAN:
458 case TargetOpcode::G_FASIN:
460 case TargetOpcode::G_FACOS:
462 case TargetOpcode::G_FATAN:
464 case TargetOpcode::G_FATAN2:
466 case TargetOpcode::G_FSINH:
468 case TargetOpcode::G_FCOSH:
470 case TargetOpcode::G_FTANH:
472 case TargetOpcode::G_FSINCOS:
474 case TargetOpcode::G_FLOG10:
476 case TargetOpcode::G_FLOG:
478 case TargetOpcode::G_FLOG2:
480 case TargetOpcode::G_FLDEXP:
482 case TargetOpcode::G_FCEIL:
484 case TargetOpcode::G_FFLOOR:
486 case TargetOpcode::G_FMINNUM:
488 case TargetOpcode::G_FMAXNUM:
490 case TargetOpcode::G_FMINIMUMNUM:
492 case TargetOpcode::G_FMAXIMUMNUM:
494 case TargetOpcode::G_FSQRT:
496 case TargetOpcode::G_FRINT:
498 case TargetOpcode::G_FNEARBYINT:
500 case TargetOpcode::G_INTRINSIC_TRUNC:
502 case TargetOpcode::G_INTRINSIC_ROUND:
504 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
506 case TargetOpcode::G_INTRINSIC_LRINT:
508 case TargetOpcode::G_INTRINSIC_LLRINT:
528 AttributeList CallerAttrs =
F.getAttributes();
529 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
530 .removeAttribute(Attribute::NoAlias)
531 .removeAttribute(Attribute::NonNull)
536 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
537 CallerAttrs.hasRetAttr(Attribute::SExt))
548 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
555 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
563 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
566 if (Ret->getNumImplicitOperands() != 1)
569 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
593 Info.OrigRet = Result;
596 (Result.Ty->isVoidTy() ||
602 if (!CLI.lowerCall(MIRBuilder, Info))
605 if (
MI && Info.LoweredTailCall) {
606 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
616 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
617 "Expected instr following MI to be return or debug inst?");
620 Next->eraseFromParent();
621 }
while (
MI->getNextNode());
635 const char *Name = TLI.getLibcallName(
Libcall);
639 return createLibcall(MIRBuilder, Name, Result, Args, CC, LocObserver,
MI);
651 Args.push_back({MO.getReg(), OpType, 0});
653 {
MI.getOperand(0).getReg(), OpType, 0}, Args,
660 MachineFunction &MF = *
MI.getMF();
666 LLT DstTy = MRI.getType(DstSin);
671 unsigned AddrSpace =
DL.getAllocaAddrSpace();
672 MachinePointerInfo PtrInfo;
690 if (LibcallResult != LegalizeResult::Legalized)
698 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
699 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
700 MI.eraseFromParent();
712 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
716 LLT OpLLT =
MRI.getType(Reg);
717 Type *OpTy =
nullptr;
722 Args.push_back({Reg, OpTy, 0});
727 RTLIB::Libcall RTLibcall;
728 unsigned Opc =
MI.getOpcode();
731 case TargetOpcode::G_BZERO:
732 RTLibcall = RTLIB::BZERO;
733 Name = TLI.getLibcallName(RTLibcall);
735 case TargetOpcode::G_MEMCPY:
736 RTLibcall = RTLIB::MEMCPY;
737 Name = TLI.getMemcpyName();
738 Args[0].Flags[0].setReturned();
740 case TargetOpcode::G_MEMMOVE:
741 RTLibcall = RTLIB::MEMMOVE;
742 Name = TLI.getLibcallName(RTLibcall);
743 Args[0].Flags[0].setReturned();
745 case TargetOpcode::G_MEMSET:
746 RTLibcall = RTLIB::MEMSET;
747 Name = TLI.getLibcallName(RTLibcall);
748 Args[0].Flags[0].setReturned();
762 Info.
CallConv = TLI.getLibcallCallingConv(RTLibcall);
766 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
770 if (!CLI.lowerCall(MIRBuilder, Info))
773 if (Info.LoweredTailCall) {
774 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
784 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
785 "Expected instr following MI to be return or debug inst?");
788 Next->eraseFromParent();
789 }
while (
MI.getNextNode());
799 unsigned Opc =
MI.getOpcode();
801 auto &MMO = AtomicMI.getMMO();
802 auto Ordering = MMO.getMergedOrdering();
803 LLT MemType = MMO.getMemoryType();
806 return RTLIB::UNKNOWN_LIBCALL;
808#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
810 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
812 case TargetOpcode::G_ATOMIC_CMPXCHG:
813 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
814 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
815 return getOutlineAtomicHelper(LC, Ordering, MemSize);
817 case TargetOpcode::G_ATOMICRMW_XCHG: {
818 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
819 return getOutlineAtomicHelper(LC, Ordering, MemSize);
821 case TargetOpcode::G_ATOMICRMW_ADD:
822 case TargetOpcode::G_ATOMICRMW_SUB: {
823 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
824 return getOutlineAtomicHelper(LC, Ordering, MemSize);
826 case TargetOpcode::G_ATOMICRMW_AND: {
827 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
828 return getOutlineAtomicHelper(LC, Ordering, MemSize);
830 case TargetOpcode::G_ATOMICRMW_OR: {
831 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
832 return getOutlineAtomicHelper(LC, Ordering, MemSize);
834 case TargetOpcode::G_ATOMICRMW_XOR: {
835 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
836 return getOutlineAtomicHelper(LC, Ordering, MemSize);
839 return RTLIB::UNKNOWN_LIBCALL;
852 unsigned Opc =
MI.getOpcode();
854 case TargetOpcode::G_ATOMIC_CMPXCHG:
855 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
858 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
859 MI.getFirst4RegLLTs();
862 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
863 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
864 NewLLT) =
MI.getFirst5RegLLTs();
874 case TargetOpcode::G_ATOMICRMW_XCHG:
875 case TargetOpcode::G_ATOMICRMW_ADD:
876 case TargetOpcode::G_ATOMICRMW_SUB:
877 case TargetOpcode::G_ATOMICRMW_AND:
878 case TargetOpcode::G_ATOMICRMW_OR:
879 case TargetOpcode::G_ATOMICRMW_XOR: {
880 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
883 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
887 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
902 const char *Name = TLI.getLibcallName(RTLibcall);
912 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
917 if (!CLI.lowerCall(MIRBuilder,
Info))
929 case TargetOpcode::G_FPEXT:
931 case TargetOpcode::G_FPTRUNC:
933 case TargetOpcode::G_FPTOSI:
935 case TargetOpcode::G_FPTOUI:
937 case TargetOpcode::G_SITOFP:
939 case TargetOpcode::G_UITOFP:
950 if (FromType->isIntegerTy()) {
952 Arg.
Flags[0].setSExt();
954 Arg.
Flags[0].setZExt();
959 {
MI.getOperand(0).getReg(), ToType, 0}, Arg, LocObserver,
965 RTLIB::Libcall RTLibcall;
966 switch (
MI.getOpcode()) {
967 case TargetOpcode::G_GET_FPENV:
968 RTLibcall = RTLIB::FEGETENV;
970 case TargetOpcode::G_SET_FPENV:
971 case TargetOpcode::G_RESET_FPENV:
972 RTLibcall = RTLIB::FESETENV;
974 case TargetOpcode::G_GET_FPMODE:
975 RTLibcall = RTLIB::FEGETMODE;
977 case TargetOpcode::G_SET_FPMODE:
978 case TargetOpcode::G_RESET_FPMODE:
979 RTLibcall = RTLIB::FESETMODE;
1012 LLT StateTy = MRI.getType(Dst);
1015 MachinePointerInfo TempPtrInfo;
1019 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1025 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1026 LocObserver,
nullptr);
1033 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1052 LLT StateTy = MRI.getType(Src);
1055 MachinePointerInfo TempPtrInfo;
1064 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1069 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1070 LocObserver,
nullptr);
1076static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1078#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1082 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1084 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1086 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1088 llvm_unreachable("unexpected size"); \
1120 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1123 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1130 LLT DstTy = MRI.getType(DstReg);
1131 const auto Cond =
Cmp->getCond();
1136 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1141 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1145 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1152 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1158 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1160 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1173 const auto [OeqLibcall, OeqPred] =
1175 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1177 const auto [UnoLibcall, UnoPred] =
1179 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1194 const auto [OeqLibcall, OeqPred] =
1199 const auto [UnoLibcall, UnoPred] =
1204 if (NotOeq && NotUno)
1223 const auto [InversedLibcall, InversedPred] =
1225 if (!BuildLibcall(InversedLibcall,
1251 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1253 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1256 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1262 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}),
1268 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1270 switch (
MI.getOpcode()) {
1273 case TargetOpcode::G_MUL:
1274 case TargetOpcode::G_SDIV:
1275 case TargetOpcode::G_UDIV:
1276 case TargetOpcode::G_SREM:
1277 case TargetOpcode::G_UREM:
1278 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1279 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1287 case TargetOpcode::G_FADD:
1288 case TargetOpcode::G_FSUB:
1289 case TargetOpcode::G_FMUL:
1290 case TargetOpcode::G_FDIV:
1291 case TargetOpcode::G_FMA:
1292 case TargetOpcode::G_FPOW:
1293 case TargetOpcode::G_FREM:
1294 case TargetOpcode::G_FCOS:
1295 case TargetOpcode::G_FSIN:
1296 case TargetOpcode::G_FTAN:
1297 case TargetOpcode::G_FACOS:
1298 case TargetOpcode::G_FASIN:
1299 case TargetOpcode::G_FATAN:
1300 case TargetOpcode::G_FATAN2:
1301 case TargetOpcode::G_FCOSH:
1302 case TargetOpcode::G_FSINH:
1303 case TargetOpcode::G_FTANH:
1304 case TargetOpcode::G_FLOG10:
1305 case TargetOpcode::G_FLOG:
1306 case TargetOpcode::G_FLOG2:
1307 case TargetOpcode::G_FEXP:
1308 case TargetOpcode::G_FEXP2:
1309 case TargetOpcode::G_FEXP10:
1310 case TargetOpcode::G_FCEIL:
1311 case TargetOpcode::G_FFLOOR:
1312 case TargetOpcode::G_FMINNUM:
1313 case TargetOpcode::G_FMAXNUM:
1314 case TargetOpcode::G_FMINIMUMNUM:
1315 case TargetOpcode::G_FMAXIMUMNUM:
1316 case TargetOpcode::G_FSQRT:
1317 case TargetOpcode::G_FRINT:
1318 case TargetOpcode::G_FNEARBYINT:
1319 case TargetOpcode::G_INTRINSIC_TRUNC:
1320 case TargetOpcode::G_INTRINSIC_ROUND:
1321 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1322 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1326 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1334 case TargetOpcode::G_FSINCOS: {
1335 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1339 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1344 case TargetOpcode::G_LROUND:
1345 case TargetOpcode::G_LLROUND:
1346 case TargetOpcode::G_INTRINSIC_LRINT:
1347 case TargetOpcode::G_INTRINSIC_LLRINT: {
1348 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1352 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1354 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1360 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1363 MI.eraseFromParent();
1366 case TargetOpcode::G_FPOWI:
1367 case TargetOpcode::G_FLDEXP: {
1368 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1372 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1374 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1379 {
MI.getOperand(1).getReg(), HLTy, 0},
1380 {
MI.getOperand(2).getReg(), ITy, 1}};
1381 Args[1].Flags[0].setSExt();
1384 Args, LocObserver, &
MI);
1389 case TargetOpcode::G_FPEXT:
1390 case TargetOpcode::G_FPTRUNC: {
1393 if (!FromTy || !ToTy)
1401 case TargetOpcode::G_FCMP: {
1405 MI.eraseFromParent();
1408 case TargetOpcode::G_FPTOSI:
1409 case TargetOpcode::G_FPTOUI: {
1413 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1414 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1422 case TargetOpcode::G_SITOFP:
1423 case TargetOpcode::G_UITOFP: {
1424 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1427 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1429 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1432 LocObserver, TLI, IsSigned);
1437 case TargetOpcode::G_ATOMICRMW_XCHG:
1438 case TargetOpcode::G_ATOMICRMW_ADD:
1439 case TargetOpcode::G_ATOMICRMW_SUB:
1440 case TargetOpcode::G_ATOMICRMW_AND:
1441 case TargetOpcode::G_ATOMICRMW_OR:
1442 case TargetOpcode::G_ATOMICRMW_XOR:
1443 case TargetOpcode::G_ATOMIC_CMPXCHG:
1444 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1450 case TargetOpcode::G_BZERO:
1451 case TargetOpcode::G_MEMCPY:
1452 case TargetOpcode::G_MEMMOVE:
1453 case TargetOpcode::G_MEMSET: {
1458 MI.eraseFromParent();
1461 case TargetOpcode::G_GET_FPENV:
1462 case TargetOpcode::G_GET_FPMODE: {
1468 case TargetOpcode::G_SET_FPENV:
1469 case TargetOpcode::G_SET_FPMODE: {
1475 case TargetOpcode::G_RESET_FPENV:
1476 case TargetOpcode::G_RESET_FPMODE: {
1485 MI.eraseFromParent();
1492 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1495 switch (
MI.getOpcode()) {
1498 case TargetOpcode::G_IMPLICIT_DEF: {
1500 LLT DstTy = MRI.getType(DstReg);
1508 if (SizeOp0 % NarrowSize != 0) {
1509 LLT ImplicitTy = NarrowTy;
1516 MI.eraseFromParent();
1520 int NumParts = SizeOp0 / NarrowSize;
1523 for (
int i = 0; i < NumParts; ++i)
1527 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1529 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1530 MI.eraseFromParent();
1533 case TargetOpcode::G_CONSTANT: {
1534 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1535 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1536 unsigned TotalSize = Ty.getSizeInBits();
1538 int NumParts = TotalSize / NarrowSize;
1541 for (
int I = 0;
I != NumParts; ++
I) {
1542 unsigned Offset =
I * NarrowSize;
1549 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1551 if (LeftoverBits != 0) {
1555 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1559 insertParts(
MI.getOperand(0).getReg(),
1560 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1562 MI.eraseFromParent();
1565 case TargetOpcode::G_SEXT:
1566 case TargetOpcode::G_ZEXT:
1567 case TargetOpcode::G_ANYEXT:
1569 case TargetOpcode::G_TRUNC: {
1573 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1575 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1579 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1580 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1581 MI.eraseFromParent();
1584 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1585 case TargetOpcode::G_FREEZE: {
1589 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1594 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1596 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1598 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1602 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1603 MI.eraseFromParent();
1606 case TargetOpcode::G_ADD:
1607 case TargetOpcode::G_SUB:
1608 case TargetOpcode::G_SADDO:
1609 case TargetOpcode::G_SSUBO:
1610 case TargetOpcode::G_SADDE:
1611 case TargetOpcode::G_SSUBE:
1612 case TargetOpcode::G_UADDO:
1613 case TargetOpcode::G_USUBO:
1614 case TargetOpcode::G_UADDE:
1615 case TargetOpcode::G_USUBE:
1617 case TargetOpcode::G_MUL:
1618 case TargetOpcode::G_UMULH:
1620 case TargetOpcode::G_EXTRACT:
1622 case TargetOpcode::G_INSERT:
1624 case TargetOpcode::G_LOAD: {
1626 Register DstReg = LoadMI.getDstReg();
1627 LLT DstTy = MRI.getType(DstReg);
1631 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1632 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1633 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1635 LoadMI.eraseFromParent();
1641 case TargetOpcode::G_ZEXTLOAD:
1642 case TargetOpcode::G_SEXTLOAD: {
1644 Register DstReg = LoadMI.getDstReg();
1645 Register PtrReg = LoadMI.getPointerReg();
1647 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1648 auto &MMO = LoadMI.getMMO();
1651 if (MemSize == NarrowSize) {
1653 }
else if (MemSize < NarrowSize) {
1654 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1655 }
else if (MemSize > NarrowSize) {
1665 LoadMI.eraseFromParent();
1668 case TargetOpcode::G_STORE: {
1671 Register SrcReg = StoreMI.getValueReg();
1672 LLT SrcTy = MRI.getType(SrcReg);
1673 if (SrcTy.isVector())
1676 int NumParts = SizeOp0 / NarrowSize;
1678 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1679 if (SrcTy.isVector() && LeftoverBits != 0)
1682 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1683 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1685 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1686 StoreMI.eraseFromParent();
1692 case TargetOpcode::G_SELECT:
1694 case TargetOpcode::G_AND:
1695 case TargetOpcode::G_OR:
1696 case TargetOpcode::G_XOR: {
1708 case TargetOpcode::G_SHL:
1709 case TargetOpcode::G_LSHR:
1710 case TargetOpcode::G_ASHR:
1712 case TargetOpcode::G_CTLZ:
1713 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1714 case TargetOpcode::G_CTTZ:
1715 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1716 case TargetOpcode::G_CTPOP:
1718 switch (
MI.getOpcode()) {
1719 case TargetOpcode::G_CTLZ:
1720 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1722 case TargetOpcode::G_CTTZ:
1723 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1725 case TargetOpcode::G_CTPOP:
1735 case TargetOpcode::G_INTTOPTR:
1743 case TargetOpcode::G_PTRTOINT:
1751 case TargetOpcode::G_PHI: {
1754 if (SizeOp0 % NarrowSize != 0)
1757 unsigned NumParts = SizeOp0 / NarrowSize;
1761 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1769 for (
unsigned i = 0; i < NumParts; ++i) {
1770 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1772 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1773 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1774 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1777 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1779 MI.eraseFromParent();
1782 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1783 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1787 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1793 case TargetOpcode::G_ICMP: {
1795 LLT SrcTy = MRI.getType(LHS);
1801 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1807 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1808 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1814 LLT ResTy = MRI.getType(Dst);
1819 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1821 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1822 auto LHS = std::get<0>(LHSAndRHS);
1823 auto RHS = std::get<1>(LHSAndRHS);
1824 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1831 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1832 auto LHS = std::get<0>(LHSAndRHS);
1833 auto RHS = std::get<1>(LHSAndRHS);
1834 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1835 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1836 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1837 TargetOpcode::G_ZEXT);
1844 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1845 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1846 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1851 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1855 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1860 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1864 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1867 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1870 LHSPartRegs[
I], RHSPartRegs[
I]);
1871 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1877 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1881 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1886 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1890 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1891 RHSLeftoverRegs[
I]);
1893 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1894 RHSLeftoverRegs[
I]);
1897 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1898 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1904 MI.eraseFromParent();
1907 case TargetOpcode::G_FCMP:
1916 case TargetOpcode::G_SEXT_INREG: {
1920 int64_t SizeInBits =
MI.getOperand(2).getImm();
1929 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
1930 MO1.
setReg(TruncMIB.getReg(0));
1933 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
1945 if (SizeOp0 % NarrowSize != 0)
1947 int NumParts = SizeOp0 / NarrowSize;
1955 for (
int i = 0; i < NumParts; ++i) {
1956 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
1971 for (
int i = 0; i < NumParts; ++i) {
1974 PartialExtensionReg = DstRegs.
back();
1976 assert(PartialExtensionReg &&
1977 "Expected to visit partial extension before full");
1978 if (FullExtensionReg) {
1983 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
1985 FullExtensionReg = DstRegs.
back();
1990 TargetOpcode::G_SEXT_INREG, {NarrowTy},
1993 PartialExtensionReg = DstRegs.
back();
1999 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2000 MI.eraseFromParent();
2003 case TargetOpcode::G_BSWAP:
2004 case TargetOpcode::G_BITREVERSE: {
2005 if (SizeOp0 % NarrowSize != 0)
2010 unsigned NumParts = SizeOp0 / NarrowSize;
2011 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2014 for (
unsigned i = 0; i < NumParts; ++i) {
2015 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2016 {SrcRegs[NumParts - 1 - i]});
2020 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2023 MI.eraseFromParent();
2026 case TargetOpcode::G_PTR_ADD:
2027 case TargetOpcode::G_PTRMASK: {
2035 case TargetOpcode::G_FPTOUI:
2036 case TargetOpcode::G_FPTOSI:
2037 case TargetOpcode::G_FPTOUI_SAT:
2038 case TargetOpcode::G_FPTOSI_SAT:
2040 case TargetOpcode::G_FPEXT:
2047 case TargetOpcode::G_FLDEXP:
2048 case TargetOpcode::G_STRICT_FLDEXP:
2050 case TargetOpcode::G_VSCALE: {
2052 LLT Ty = MRI.getType(Dst);
2056 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2057 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2058 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2061 MI.eraseFromParent();
2068 LLT Ty = MRI.getType(Val);
2074 if (Ty.isPointer()) {
2075 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2077 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2083 if (Ty.isPointerVector())
2084 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2085 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2089 unsigned OpIdx,
unsigned ExtOpcode) {
2091 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2092 MO.
setReg(ExtB.getReg(0));
2098 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2099 MO.
setReg(ExtB.getReg(0));
2103 unsigned OpIdx,
unsigned TruncOpcode) {
2105 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2107 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2112 unsigned OpIdx,
unsigned ExtOpcode) {
2114 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2116 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2125 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2127 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2133 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2143 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2150LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2155 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2156 if (DstTy.isVector())
2159 LLT SrcTy =
MRI.getType(Src1Reg);
2160 const int DstSize = DstTy.getSizeInBits();
2161 const int SrcSize = SrcTy.getSizeInBits();
2163 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2165 unsigned NumOps =
MI.getNumOperands();
2166 unsigned NumSrc =
MI.getNumOperands() - 1;
2167 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2169 if (WideSize >= DstSize) {
2173 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2174 const unsigned Offset = (
I - 1) * PartSize;
2182 MRI.createGenericVirtualRegister(WideTy);
2187 ResultReg = NextResult;
2190 if (WideSize > DstSize)
2192 else if (DstTy.isPointer())
2195 MI.eraseFromParent();
2220 const int GCD = std::gcd(SrcSize, WideSize);
2230 if (GCD == SrcSize) {
2233 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2234 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2240 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2242 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2246 const int PartsPerGCD = WideSize / GCD;
2250 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2252 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2259 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2261 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2262 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2265 MI.eraseFromParent();
2270LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2275 int NumDst =
MI.getNumOperands() - 1;
2276 Register SrcReg =
MI.getOperand(NumDst).getReg();
2277 LLT SrcTy = MRI.getType(SrcReg);
2281 Register Dst0Reg =
MI.getOperand(0).getReg();
2282 LLT DstTy = MRI.getType(Dst0Reg);
2291 dbgs() <<
"Not casting non-integral address space integer\n");
2296 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2304 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2312 for (
int I = 1;
I != NumDst; ++
I) {
2313 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2314 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2318 MI.eraseFromParent();
2329 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2333 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2336 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2354 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2359 if (PartsPerRemerge == 1) {
2362 for (
int I = 0;
I != NumUnmerge; ++
I) {
2363 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2365 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2366 int Idx =
I * PartsPerUnmerge + J;
2368 MIB.addDef(
MI.getOperand(Idx).getReg());
2371 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2375 MIB.addUse(Unmerge.getReg(
I));
2378 SmallVector<Register, 16> Parts;
2379 for (
int J = 0; J != NumUnmerge; ++J)
2380 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2383 for (
int I = 0;
I != NumDst; ++
I) {
2384 for (
int J = 0; J < PartsPerRemerge; ++J) {
2385 const int Idx =
I * PartsPerRemerge + J;
2389 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2390 RemergeParts.
clear();
2394 MI.eraseFromParent();
2399LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2401 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2402 unsigned Offset =
MI.getOperand(2).getImm();
2405 if (SrcTy.
isVector() || DstTy.isVector())
2417 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2421 if (DstTy.isPointer())
2428 MI.eraseFromParent();
2433 LLT ShiftTy = SrcTy;
2442 MI.eraseFromParent();
2473LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2475 if (TypeIdx != 0 || WideTy.
isVector())
2485LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2489 std::optional<Register> CarryIn;
2490 switch (
MI.getOpcode()) {
2493 case TargetOpcode::G_SADDO:
2494 Opcode = TargetOpcode::G_ADD;
2495 ExtOpcode = TargetOpcode::G_SEXT;
2497 case TargetOpcode::G_SSUBO:
2498 Opcode = TargetOpcode::G_SUB;
2499 ExtOpcode = TargetOpcode::G_SEXT;
2501 case TargetOpcode::G_UADDO:
2502 Opcode = TargetOpcode::G_ADD;
2503 ExtOpcode = TargetOpcode::G_ZEXT;
2505 case TargetOpcode::G_USUBO:
2506 Opcode = TargetOpcode::G_SUB;
2507 ExtOpcode = TargetOpcode::G_ZEXT;
2509 case TargetOpcode::G_SADDE:
2510 Opcode = TargetOpcode::G_UADDE;
2511 ExtOpcode = TargetOpcode::G_SEXT;
2512 CarryIn =
MI.getOperand(4).getReg();
2514 case TargetOpcode::G_SSUBE:
2515 Opcode = TargetOpcode::G_USUBE;
2516 ExtOpcode = TargetOpcode::G_SEXT;
2517 CarryIn =
MI.getOperand(4).getReg();
2519 case TargetOpcode::G_UADDE:
2520 Opcode = TargetOpcode::G_UADDE;
2521 ExtOpcode = TargetOpcode::G_ZEXT;
2522 CarryIn =
MI.getOperand(4).getReg();
2524 case TargetOpcode::G_USUBE:
2525 Opcode = TargetOpcode::G_USUBE;
2526 ExtOpcode = TargetOpcode::G_ZEXT;
2527 CarryIn =
MI.getOperand(4).getReg();
2543 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2544 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2548 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2550 .buildInstr(Opcode, {WideTy, CarryOutTy},
2551 {LHSExt, RHSExt, *CarryIn})
2554 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2556 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2557 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2558 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2563 MI.eraseFromParent();
2568LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2570 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2571 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2572 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2573 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2574 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2587 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2594 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2598 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2599 {ShiftL, ShiftR},
MI.getFlags());
2604 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2607 MI.eraseFromParent();
2612LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2621 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2623 LLT SrcTy = MRI.getType(
LHS);
2624 LLT OverflowTy = MRI.getType(OriginalOverflow);
2631 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2632 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2633 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2640 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2642 MachineInstrBuilder Mulo;
2643 if (WideMulCanOverflow)
2644 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2645 {LeftOperand, RightOperand});
2647 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2652 MachineInstrBuilder ExtResult;
2659 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2663 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2666 if (WideMulCanOverflow) {
2674 MI.eraseFromParent();
2680 unsigned Opcode =
MI.getOpcode();
2684 case TargetOpcode::G_ATOMICRMW_XCHG:
2685 case TargetOpcode::G_ATOMICRMW_ADD:
2686 case TargetOpcode::G_ATOMICRMW_SUB:
2687 case TargetOpcode::G_ATOMICRMW_AND:
2688 case TargetOpcode::G_ATOMICRMW_OR:
2689 case TargetOpcode::G_ATOMICRMW_XOR:
2690 case TargetOpcode::G_ATOMICRMW_MIN:
2691 case TargetOpcode::G_ATOMICRMW_MAX:
2692 case TargetOpcode::G_ATOMICRMW_UMIN:
2693 case TargetOpcode::G_ATOMICRMW_UMAX:
2694 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2700 case TargetOpcode::G_ATOMIC_CMPXCHG:
2701 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2708 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2718 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2723 case TargetOpcode::G_EXTRACT:
2724 return widenScalarExtract(
MI, TypeIdx, WideTy);
2725 case TargetOpcode::G_INSERT:
2726 return widenScalarInsert(
MI, TypeIdx, WideTy);
2727 case TargetOpcode::G_MERGE_VALUES:
2728 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2729 case TargetOpcode::G_UNMERGE_VALUES:
2730 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2731 case TargetOpcode::G_SADDO:
2732 case TargetOpcode::G_SSUBO:
2733 case TargetOpcode::G_UADDO:
2734 case TargetOpcode::G_USUBO:
2735 case TargetOpcode::G_SADDE:
2736 case TargetOpcode::G_SSUBE:
2737 case TargetOpcode::G_UADDE:
2738 case TargetOpcode::G_USUBE:
2739 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2740 case TargetOpcode::G_UMULO:
2741 case TargetOpcode::G_SMULO:
2742 return widenScalarMulo(
MI, TypeIdx, WideTy);
2743 case TargetOpcode::G_SADDSAT:
2744 case TargetOpcode::G_SSUBSAT:
2745 case TargetOpcode::G_SSHLSAT:
2746 case TargetOpcode::G_UADDSAT:
2747 case TargetOpcode::G_USUBSAT:
2748 case TargetOpcode::G_USHLSAT:
2749 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2750 case TargetOpcode::G_CTTZ:
2751 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2752 case TargetOpcode::G_CTLZ:
2753 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
2754 case TargetOpcode::G_CTPOP: {
2765 unsigned ExtOpc = Opcode == TargetOpcode::G_CTTZ ||
2766 Opcode == TargetOpcode::G_CTTZ_ZERO_UNDEF
2767 ? TargetOpcode::G_ANYEXT
2768 : TargetOpcode::G_ZEXT;
2769 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2770 LLT CurTy = MRI.getType(SrcReg);
2771 unsigned NewOpc = Opcode;
2772 if (NewOpc == TargetOpcode::G_CTTZ) {
2779 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2781 NewOpc = TargetOpcode::G_CTTZ_ZERO_UNDEF;
2786 if (Opcode == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
2796 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2798 if (Opcode == TargetOpcode::G_CTLZ) {
2801 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff));
2804 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2805 MI.eraseFromParent();
2808 case TargetOpcode::G_BSWAP: {
2812 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2813 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2814 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2817 MI.getOperand(0).setReg(DstExt);
2821 LLT Ty = MRI.getType(DstReg);
2823 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2824 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2830 case TargetOpcode::G_BITREVERSE: {
2834 LLT Ty = MRI.getType(DstReg);
2837 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2839 MI.getOperand(0).setReg(DstExt);
2842 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2843 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2848 case TargetOpcode::G_FREEZE:
2849 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2856 case TargetOpcode::G_ABS:
2863 case TargetOpcode::G_ADD:
2864 case TargetOpcode::G_AND:
2865 case TargetOpcode::G_MUL:
2866 case TargetOpcode::G_OR:
2867 case TargetOpcode::G_XOR:
2868 case TargetOpcode::G_SUB:
2869 case TargetOpcode::G_SHUFFLE_VECTOR:
2880 case TargetOpcode::G_SBFX:
2881 case TargetOpcode::G_UBFX:
2895 case TargetOpcode::G_SHL:
2911 case TargetOpcode::G_ROTR:
2912 case TargetOpcode::G_ROTL:
2921 case TargetOpcode::G_SDIV:
2922 case TargetOpcode::G_SREM:
2923 case TargetOpcode::G_SMIN:
2924 case TargetOpcode::G_SMAX:
2925 case TargetOpcode::G_ABDS:
2933 case TargetOpcode::G_SDIVREM:
2942 case TargetOpcode::G_ASHR:
2943 case TargetOpcode::G_LSHR:
2947 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
2948 : TargetOpcode::G_ZEXT;
2961 case TargetOpcode::G_UDIV:
2962 case TargetOpcode::G_UREM:
2963 case TargetOpcode::G_ABDU:
2970 case TargetOpcode::G_UDIVREM:
2978 case TargetOpcode::G_UMIN:
2979 case TargetOpcode::G_UMAX: {
2980 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
2982 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
2986 ? TargetOpcode::G_SEXT
2987 : TargetOpcode::G_ZEXT;
2997 case TargetOpcode::G_SELECT:
3007 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3014 case TargetOpcode::G_FPTOSI:
3015 case TargetOpcode::G_FPTOUI:
3016 case TargetOpcode::G_INTRINSIC_LRINT:
3017 case TargetOpcode::G_INTRINSIC_LLRINT:
3018 case TargetOpcode::G_IS_FPCLASS:
3028 case TargetOpcode::G_SITOFP:
3038 case TargetOpcode::G_UITOFP:
3048 case TargetOpcode::G_FPTOSI_SAT:
3049 case TargetOpcode::G_FPTOUI_SAT:
3054 LLT Ty = MRI.getType(OldDst);
3055 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3057 MI.getOperand(0).setReg(ExtReg);
3058 uint64_t ShortBits = Ty.getScalarSizeInBits();
3061 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3072 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3073 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3081 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3089 case TargetOpcode::G_LOAD:
3090 case TargetOpcode::G_SEXTLOAD:
3091 case TargetOpcode::G_ZEXTLOAD:
3097 case TargetOpcode::G_STORE: {
3101 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3102 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3103 if (!Ty.isScalar()) {
3111 MI.setMemRefs(MF, {NewMMO});
3118 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3119 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3125 case TargetOpcode::G_CONSTANT: {
3128 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3129 MRI.getType(
MI.getOperand(0).getReg()));
3130 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3131 ExtOpc == TargetOpcode::G_ANYEXT) &&
3134 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3138 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3144 case TargetOpcode::G_FCONSTANT: {
3150 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3152 MI.eraseFromParent();
3155 case TargetOpcode::G_IMPLICIT_DEF: {
3161 case TargetOpcode::G_BRCOND:
3167 case TargetOpcode::G_FCMP:
3178 case TargetOpcode::G_ICMP:
3183 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3187 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3188 unsigned ExtOpcode =
3192 ? TargetOpcode::G_SEXT
3193 : TargetOpcode::G_ZEXT;
3200 case TargetOpcode::G_PTR_ADD:
3201 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3207 case TargetOpcode::G_PHI: {
3208 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3211 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3223 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3226 LLT VecTy = MRI.getType(VecReg);
3231 TargetOpcode::G_ANYEXT);
3246 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3262 LLT VecTy = MRI.getType(VecReg);
3282 case TargetOpcode::G_FADD:
3283 case TargetOpcode::G_FMUL:
3284 case TargetOpcode::G_FSUB:
3285 case TargetOpcode::G_FMA:
3286 case TargetOpcode::G_FMAD:
3287 case TargetOpcode::G_FNEG:
3288 case TargetOpcode::G_FABS:
3289 case TargetOpcode::G_FCANONICALIZE:
3290 case TargetOpcode::G_FMINNUM:
3291 case TargetOpcode::G_FMAXNUM:
3292 case TargetOpcode::G_FMINNUM_IEEE:
3293 case TargetOpcode::G_FMAXNUM_IEEE:
3294 case TargetOpcode::G_FMINIMUM:
3295 case TargetOpcode::G_FMAXIMUM:
3296 case TargetOpcode::G_FMINIMUMNUM:
3297 case TargetOpcode::G_FMAXIMUMNUM:
3298 case TargetOpcode::G_FDIV:
3299 case TargetOpcode::G_FREM:
3300 case TargetOpcode::G_FCEIL:
3301 case TargetOpcode::G_FFLOOR:
3302 case TargetOpcode::G_FCOS:
3303 case TargetOpcode::G_FSIN:
3304 case TargetOpcode::G_FTAN:
3305 case TargetOpcode::G_FACOS:
3306 case TargetOpcode::G_FASIN:
3307 case TargetOpcode::G_FATAN:
3308 case TargetOpcode::G_FATAN2:
3309 case TargetOpcode::G_FCOSH:
3310 case TargetOpcode::G_FSINH:
3311 case TargetOpcode::G_FTANH:
3312 case TargetOpcode::G_FLOG10:
3313 case TargetOpcode::G_FLOG:
3314 case TargetOpcode::G_FLOG2:
3315 case TargetOpcode::G_FRINT:
3316 case TargetOpcode::G_FNEARBYINT:
3317 case TargetOpcode::G_FSQRT:
3318 case TargetOpcode::G_FEXP:
3319 case TargetOpcode::G_FEXP2:
3320 case TargetOpcode::G_FEXP10:
3321 case TargetOpcode::G_FPOW:
3322 case TargetOpcode::G_INTRINSIC_TRUNC:
3323 case TargetOpcode::G_INTRINSIC_ROUND:
3324 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3328 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3334 case TargetOpcode::G_FPOWI:
3335 case TargetOpcode::G_FLDEXP:
3336 case TargetOpcode::G_STRICT_FLDEXP: {
3338 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3359 case TargetOpcode::G_FFREXP: {
3372 case TargetOpcode::G_INTTOPTR:
3380 case TargetOpcode::G_PTRTOINT:
3388 case TargetOpcode::G_BUILD_VECTOR: {
3392 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3398 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3406 case TargetOpcode::G_SEXT_INREG:
3415 case TargetOpcode::G_PTRMASK: {
3423 case TargetOpcode::G_VECREDUCE_ADD: {
3432 case TargetOpcode::G_VECREDUCE_FADD:
3433 case TargetOpcode::G_VECREDUCE_FMUL:
3434 case TargetOpcode::G_VECREDUCE_FMIN:
3435 case TargetOpcode::G_VECREDUCE_FMAX:
3436 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3437 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3442 LLT VecTy = MRI.getType(VecReg);
3451 case TargetOpcode::G_VSCALE: {
3458 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3463 case TargetOpcode::G_SPLAT_VECTOR: {
3472 case TargetOpcode::G_INSERT_SUBVECTOR: {
3480 LLT SubVecTy = MRI.getType(SubVec);
3484 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3485 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3486 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3490 auto SplatZero =
MIRBuilder.buildSplatVector(
3495 MI.eraseFromParent();
3504 auto Unmerge =
B.buildUnmerge(Ty, Src);
3505 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3514 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3516 LLT DstLLT =
MRI.getType(DstReg);
3528 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3537 MI.eraseFromParent();
3548 MI.eraseFromParent();
3555 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3556 if (SrcTy.isVector()) {
3560 if (DstTy.isVector()) {
3561 int NumDstElt = DstTy.getNumElements();
3562 int NumSrcElt = SrcTy.getNumElements();
3565 LLT DstCastTy = DstEltTy;
3566 LLT SrcPartTy = SrcEltTy;
3570 if (NumSrcElt < NumDstElt) {
3580 SrcPartTy = SrcEltTy;
3581 }
else if (NumSrcElt > NumDstElt) {
3592 DstCastTy = DstEltTy;
3597 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3601 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3602 MI.eraseFromParent();
3606 if (DstTy.isVector()) {
3609 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3610 MI.eraseFromParent();
3626 unsigned NewEltSize,
3627 unsigned OldEltSize) {
3628 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3629 LLT IdxTy =
B.getMRI()->getType(Idx);
3632 auto OffsetMask =
B.buildConstant(
3634 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3635 return B.buildShl(IdxTy, OffsetIdx,
3636 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3651 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3655 unsigned OldNumElts = SrcVecTy.getNumElements();
3662 if (NewNumElts > OldNumElts) {
3673 if (NewNumElts % OldNumElts != 0)
3677 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3681 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3684 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3686 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3687 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3688 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3689 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3690 NewOps[
I] = Elt.getReg(0);
3693 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3695 MI.eraseFromParent();
3699 if (NewNumElts < OldNumElts) {
3700 if (NewEltSize % OldEltSize != 0)
3722 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3723 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3726 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3730 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3731 ScaledIdx).getReg(0);
3739 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3741 MI.eraseFromParent();
3755 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3756 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3757 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3758 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3761 auto EltMask =
B.buildConstant(
3765 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3766 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3769 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3773 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3787 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3788 MI.getFirst4RegLLTs();
3800 if (NewNumElts < OldNumElts) {
3801 if (NewEltSize % OldEltSize != 0)
3810 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3811 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3814 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3818 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3819 ScaledIdx).getReg(0);
3829 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3830 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3834 MI.eraseFromParent();
3864 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3868 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3869 return UnableToLegalize;
3874 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3876 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3885 MI.eraseFromParent();
3903 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3904 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3914 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3915 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3917 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
3918 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
3920 MI.eraseFromParent();
3950 LLT DstTy = MRI.getType(Dst);
3951 LLT SrcTy = MRI.getType(Src);
3957 if (DstTy == CastTy)
3965 if (CastEltSize < DstEltSize)
3968 auto AdjustAmt = CastEltSize / DstEltSize;
3969 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
3970 SrcTyMinElts % AdjustAmt != 0)
3975 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
3976 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
3979 ES->eraseFromParent();
4014 LLT DstTy = MRI.getType(Dst);
4015 LLT BigVecTy = MRI.getType(BigVec);
4016 LLT SubVecTy = MRI.getType(SubVec);
4018 if (DstTy == CastTy)
4033 if (CastEltSize < DstEltSize)
4036 auto AdjustAmt = CastEltSize / DstEltSize;
4037 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4038 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4044 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4045 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4047 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4050 ES->eraseFromParent();
4058 LLT DstTy = MRI.getType(DstReg);
4066 if (MemSizeInBits != MemStoreSizeInBits) {
4083 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4087 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4088 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4090 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4093 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4095 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4098 if (DstTy != LoadTy)
4106 if (
MIRBuilder.getDataLayout().isBigEndian())
4124 uint64_t LargeSplitSize, SmallSplitSize;
4129 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4136 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4139 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4150 if (Alignment.
value() * 8 > MemSizeInBits &&
4155 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4172 LLT PtrTy = MRI.getType(PtrReg);
4175 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4179 LargeSplitSize / 8);
4180 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4181 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4183 SmallPtr, *SmallMMO);
4185 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4186 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4188 if (AnyExtTy == DstTy)
4189 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4191 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4195 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4215 LLT SrcTy = MRI.getType(SrcReg);
4223 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4229 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4231 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4235 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4239 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4254 uint64_t LargeSplitSize, SmallSplitSize;
4261 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4264 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4273 if (SrcTy.isPointer()) {
4275 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4278 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4281 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4282 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4285 LLT PtrTy = MRI.getType(PtrReg);
4288 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4294 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4295 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4304 LLT SrcTy = MRI.getType(SrcReg);
4310 assert(SrcTy.isVector() &&
"Expect a vector store type");
4317 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4321 auto Elt =
MIRBuilder.buildExtractVectorElement(
4322 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4323 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4324 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4330 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4331 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4335 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4346 switch (
MI.getOpcode()) {
4347 case TargetOpcode::G_LOAD: {
4365 case TargetOpcode::G_STORE: {
4381 case TargetOpcode::G_SELECT: {
4385 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4387 dbgs() <<
"bitcast action not implemented for vector select\n");
4398 case TargetOpcode::G_AND:
4399 case TargetOpcode::G_OR:
4400 case TargetOpcode::G_XOR: {
4408 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4410 case TargetOpcode::G_INSERT_VECTOR_ELT:
4412 case TargetOpcode::G_CONCAT_VECTORS:
4414 case TargetOpcode::G_SHUFFLE_VECTOR:
4416 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4418 case TargetOpcode::G_INSERT_SUBVECTOR:
4426void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4436 switch(
MI.getOpcode()) {
4439 case TargetOpcode::G_FCONSTANT:
4441 case TargetOpcode::G_BITCAST:
4443 case TargetOpcode::G_SREM:
4444 case TargetOpcode::G_UREM: {
4445 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4447 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4448 {MI.getOperand(1), MI.getOperand(2)});
4450 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4452 MI.eraseFromParent();
4455 case TargetOpcode::G_SADDO:
4456 case TargetOpcode::G_SSUBO:
4458 case TargetOpcode::G_SADDE:
4460 case TargetOpcode::G_SSUBE:
4462 case TargetOpcode::G_UMULH:
4463 case TargetOpcode::G_SMULH:
4465 case TargetOpcode::G_SMULO:
4466 case TargetOpcode::G_UMULO: {
4469 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4470 LLT Ty = MRI.getType(Res);
4472 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4473 ? TargetOpcode::G_SMULH
4474 : TargetOpcode::G_UMULH;
4478 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4479 MI.removeOperand(1);
4482 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4490 if (Opcode == TargetOpcode::G_SMULH) {
4491 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4492 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4499 case TargetOpcode::G_FNEG: {
4500 auto [Res, SubByReg] =
MI.getFirst2Regs();
4501 LLT Ty = MRI.getType(Res);
4505 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4506 MI.eraseFromParent();
4509 case TargetOpcode::G_FSUB:
4510 case TargetOpcode::G_STRICT_FSUB: {
4511 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4512 LLT Ty = MRI.getType(Res);
4517 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4518 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4522 MI.eraseFromParent();
4525 case TargetOpcode::G_FMAD:
4527 case TargetOpcode::G_FFLOOR:
4529 case TargetOpcode::G_LROUND:
4530 case TargetOpcode::G_LLROUND: {
4533 LLT SrcTy = MRI.getType(SrcReg);
4534 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4537 MI.eraseFromParent();
4540 case TargetOpcode::G_INTRINSIC_ROUND:
4542 case TargetOpcode::G_FRINT: {
4545 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4548 case TargetOpcode::G_INTRINSIC_LRINT:
4549 case TargetOpcode::G_INTRINSIC_LLRINT: {
4552 LLT SrcTy = MRI.getType(SrcReg);
4554 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4556 MI.eraseFromParent();
4559 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4560 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4561 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4562 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4563 **
MI.memoperands_begin());
4565 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4566 MI.eraseFromParent();
4569 case TargetOpcode::G_LOAD:
4570 case TargetOpcode::G_SEXTLOAD:
4571 case TargetOpcode::G_ZEXTLOAD:
4573 case TargetOpcode::G_STORE:
4575 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4576 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4577 case TargetOpcode::G_CTLZ:
4578 case TargetOpcode::G_CTTZ:
4579 case TargetOpcode::G_CTPOP:
4582 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4584 Register NewRes = MRI.cloneVirtualRegister(Res);
4591 MI.eraseFromParent();
4595 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4596 const LLT CondTy = MRI.getType(CarryOut);
4597 const LLT Ty = MRI.getType(Res);
4599 Register NewRes = MRI.cloneVirtualRegister(Res);
4602 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4608 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4609 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4616 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4621 MI.eraseFromParent();
4625 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4630 MI.eraseFromParent();
4634 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4635 const LLT CondTy = MRI.getType(BorrowOut);
4636 const LLT Ty = MRI.getType(Res);
4639 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4645 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4646 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4653 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4654 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4656 MI.eraseFromParent();
4689 case G_MERGE_VALUES:
4691 case G_UNMERGE_VALUES:
4693 case TargetOpcode::G_SEXT_INREG: {
4694 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4695 int64_t SizeInBits =
MI.getOperand(2).getImm();
4697 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4698 LLT DstTy = MRI.getType(DstReg);
4699 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4702 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4703 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4704 MI.eraseFromParent();
4707 case G_EXTRACT_VECTOR_ELT:
4708 case G_INSERT_VECTOR_ELT:
4710 case G_SHUFFLE_VECTOR:
4712 case G_VECTOR_COMPRESS:
4714 case G_DYN_STACKALLOC:
4718 case G_STACKRESTORE:
4728 case G_READ_REGISTER:
4729 case G_WRITE_REGISTER:
4736 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4737 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4743 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4748 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4759 bool IsSigned =
MI.getOpcode() == G_ABDS;
4760 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4761 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4762 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4786 case G_MEMCPY_INLINE:
4787 return lowerMemcpyInline(
MI);
4798 case G_ATOMICRMW_SUB: {
4799 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4800 const LLT ValTy = MRI.getType(Val);
4804 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4805 MI.eraseFromParent();
4828 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4832 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4838 Align StackTypeAlign =
4845 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4846 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4851 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4863 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4866 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4877 "Converting bits to bytes lost precision");
4883 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4884 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4886 if (IdxTy != MRI.getType(Index))
4887 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4892 LLT PtrTy = MRI.getType(VecPtr);
4893 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4901 std::initializer_list<unsigned> NonVecOpIndices) {
4902 if (
MI.getNumMemOperands() != 0)
4905 LLT VecTy =
MRI.getType(
MI.getReg(0));
4919 if (!Ty.isVector()) {
4925 if (Ty.getNumElements() != NumElts)
4940 assert(Ty.isVector() &&
"Expected vector type");
4943 int NumParts, NumLeftover;
4944 std::tie(NumParts, NumLeftover) =
4947 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
4948 for (
int i = 0; i < NumParts; ++i) {
4953 assert(NumLeftover == 1 &&
"expected exactly one leftover");
4962 for (
unsigned i = 0; i <
N; ++i) {
4964 Ops.push_back(
Op.getReg());
4965 else if (
Op.isImm())
4966 Ops.push_back(
Op.getImm());
4967 else if (
Op.isPredicate())
4989 std::initializer_list<unsigned> NonVecOpIndices) {
4991 "Non-compatible opcode or not specified non-vector operands");
4992 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
4994 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
4995 unsigned NumDefs =
MI.getNumDefs();
5003 for (
unsigned i = 0; i < NumDefs; ++i) {
5004 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5012 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5013 ++UseIdx, ++UseNo) {
5016 MI.getOperand(UseIdx));
5025 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5029 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5031 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5032 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5035 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5036 Uses.push_back(InputOpsPieces[InputNo][i]);
5039 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5040 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5045 for (
unsigned i = 0; i < NumDefs; ++i)
5046 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5048 for (
unsigned i = 0; i < NumDefs; ++i)
5049 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5052 MI.eraseFromParent();
5059 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5061 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5062 unsigned NumDefs =
MI.getNumDefs();
5066 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5071 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5072 UseIdx += 2, ++UseNo) {
5080 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5082 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5083 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5085 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5088 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5089 Phi.addUse(InputOpsPieces[j][i]);
5090 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5100 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5102 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5105 MI.eraseFromParent();
5113 const int NumDst =
MI.getNumOperands() - 1;
5114 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5115 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5116 LLT SrcTy = MRI.getType(SrcReg);
5118 if (TypeIdx != 1 || NarrowTy == DstTy)
5125 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5128 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5142 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5143 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5144 const int PartsPerUnmerge = NumDst / NumUnmerge;
5146 for (
int I = 0;
I != NumUnmerge; ++
I) {
5147 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5149 for (
int J = 0; J != PartsPerUnmerge; ++J)
5150 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5151 MIB.addUse(Unmerge.getReg(
I));
5154 MI.eraseFromParent();
5161 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5165 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5167 if (NarrowTy == SrcTy)
5175 assert(SrcTy.isVector() &&
"Expected vector types");
5177 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5191 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5192 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5193 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5199 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5200 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5201 ++i,
Offset += NumNarrowTyElts) {
5204 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5207 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5208 MI.eraseFromParent();
5212 assert(TypeIdx == 0 &&
"Bad type index");
5213 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5228 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5229 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5231 for (
unsigned i = 0; i < NumParts; ++i) {
5233 for (
unsigned j = 0; j < NumElts; ++j)
5234 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5236 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5239 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5240 MI.eraseFromParent();
5248 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5250 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5252 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5254 InsertVal =
MI.getOperand(2).getReg();
5256 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5257 LLT VecTy = MRI.getType(SrcVec);
5263 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5267 MI.eraseFromParent();
5276 SplitPieces[IdxVal] = InsertVal;
5277 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5279 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5283 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5286 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5287 TargetOpcode::G_ANYEXT);
5291 LLT IdxTy = MRI.getType(Idx);
5292 int64_t PartIdx = IdxVal / NewNumElts;
5294 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5297 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5300 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5301 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5302 VecParts[PartIdx] = InsertPart.getReg(0);
5306 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5308 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5312 MI.eraseFromParent();
5332 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5344 LLT ValTy = MRI.getType(ValReg);
5353 int NumLeftover = -1;
5359 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5361 NumParts = NarrowRegs.
size();
5362 NumLeftover = NarrowLeftoverRegs.
size();
5369 LLT PtrTy = MRI.getType(AddrReg);
5372 unsigned TotalSize = ValTy.getSizeInBits();
5379 auto MMO = LdStMI.
getMMO();
5381 unsigned NumParts,
unsigned Offset) ->
unsigned {
5384 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5386 unsigned ByteOffset =
Offset / 8;
5389 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5396 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5397 ValRegs.push_back(Dst);
5398 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5400 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5409 unsigned HandledOffset =
5410 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5414 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5417 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5418 LeftoverTy, NarrowLeftoverRegs);
5432 switch (
MI.getOpcode()) {
5433 case G_IMPLICIT_DEF:
5449 case G_FCANONICALIZE:
5466 case G_INTRINSIC_LRINT:
5467 case G_INTRINSIC_LLRINT:
5468 case G_INTRINSIC_ROUND:
5469 case G_INTRINSIC_ROUNDEVEN:
5472 case G_INTRINSIC_TRUNC:
5499 case G_FMINNUM_IEEE:
5500 case G_FMAXNUM_IEEE:
5522 case G_CTLZ_ZERO_UNDEF:
5524 case G_CTTZ_ZERO_UNDEF:
5540 case G_ADDRSPACE_CAST:
5553 case G_STRICT_FLDEXP:
5562 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5567 case G_UNMERGE_VALUES:
5569 case G_BUILD_VECTOR:
5570 assert(TypeIdx == 0 &&
"not a vector type index");
5572 case G_CONCAT_VECTORS:
5576 case G_EXTRACT_VECTOR_ELT:
5577 case G_INSERT_VECTOR_ELT:
5586 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5587 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5589 case G_SHUFFLE_VECTOR:
5595 case G_INTRINSIC_FPTRUNC_ROUND:
5605 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5606 "Not a bitcast operation");
5611 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5613 unsigned NewElemCount =
5616 if (NewElemCount == 1) {
5619 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5625 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5634 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5635 MI.eraseFromParent();
5641 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5645 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5646 MI.getFirst3RegLLTs();
5649 if (DstTy != Src1Ty)
5651 if (DstTy != Src2Ty)
5666 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5682 unsigned InputUsed[2] = {-1U, -1U};
5683 unsigned FirstMaskIdx =
High * NewElts;
5684 bool UseBuildVector =
false;
5685 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5687 int Idx = Mask[FirstMaskIdx + MaskOffset];
5692 if (
Input >= std::size(Inputs)) {
5699 Idx -=
Input * NewElts;
5703 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5704 if (InputUsed[OpNo] ==
Input) {
5707 }
else if (InputUsed[OpNo] == -1U) {
5709 InputUsed[OpNo] =
Input;
5714 if (OpNo >= std::size(InputUsed)) {
5717 UseBuildVector =
true;
5722 Ops.push_back(Idx + OpNo * NewElts);
5725 if (UseBuildVector) {
5730 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5732 int Idx = Mask[FirstMaskIdx + MaskOffset];
5737 if (
Input >= std::size(Inputs)) {
5744 Idx -=
Input * NewElts;
5748 .buildExtractVectorElement(
5749 EltTy, Inputs[
Input],
5755 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5756 }
else if (InputUsed[0] == -1U) {
5758 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5760 Register Op0 = Inputs[InputUsed[0]];
5764 : Inputs[InputUsed[1]];
5766 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5773 MI.eraseFromParent();
5786 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5792 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5795 const unsigned NumParts =
5797 : SrcTy.getNumElements();
5801 if (DstTy != NarrowTy)
5807 unsigned NumPartsLeft = NumParts;
5808 while (NumPartsLeft > 1) {
5809 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5812 .buildInstr(ScalarOpc, {NarrowTy},
5813 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5816 SplitSrcs = PartialResults;
5817 PartialResults.
clear();
5818 NumPartsLeft = SplitSrcs.
size();
5822 MI.eraseFromParent();
5827 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5828 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5831 MI.eraseFromParent();
5835 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5837 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5845 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5848 Register Acc = PartialReductions[0];
5849 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5850 if (Part == NumParts - 1) {
5852 {Acc, PartialReductions[Part]});
5855 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5859 MI.eraseFromParent();
5865 unsigned int TypeIdx,
5867 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5868 MI.getFirst3RegLLTs();
5869 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5873 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5874 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5875 "Unexpected vecreduce opcode");
5876 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5877 ? TargetOpcode::G_FADD
5878 : TargetOpcode::G_FMUL;
5881 unsigned NumParts = SrcTy.getNumElements();
5884 for (
unsigned i = 0; i < NumParts; i++)
5885 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5889 MI.eraseFromParent();
5896 unsigned ScalarOpc) {
5904 while (SplitSrcs.
size() > 1) {
5906 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
5914 SplitSrcs = std::move(PartialRdxs);
5918 MI.getOperand(1).setReg(SplitSrcs[0]);
5925 const LLT HalfTy,
const LLT AmtTy) {
5927 Register InL = MRI.createGenericVirtualRegister(HalfTy);
5928 Register InH = MRI.createGenericVirtualRegister(HalfTy);
5932 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
5933 MI.eraseFromParent();
5939 unsigned VTBits = 2 * NVTBits;
5942 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
5943 if (Amt.
ugt(VTBits)) {
5945 }
else if (Amt.
ugt(NVTBits)) {
5948 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5949 }
else if (Amt == NVTBits) {
5957 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5960 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
5961 if (Amt.
ugt(VTBits)) {
5963 }
else if (Amt.
ugt(NVTBits)) {
5965 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5967 }
else if (Amt == NVTBits) {
5971 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
5973 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
5975 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5981 if (Amt.
ugt(VTBits)) {
5983 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5984 }
else if (Amt.
ugt(NVTBits)) {
5986 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5988 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5989 }
else if (Amt == NVTBits) {
5992 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5994 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
5996 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
5998 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6005 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6006 MI.eraseFromParent();
6022 LLT DstTy = MRI.getType(DstReg);
6027 LLT ShiftAmtTy = MRI.getType(Amt);
6029 if (DstEltSize % 2 != 0)
6045 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6056 const unsigned NewBitSize = DstEltSize / 2;
6068 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6070 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6071 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6074 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6075 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6077 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6082 switch (
MI.getOpcode()) {
6083 case TargetOpcode::G_SHL: {
6085 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6087 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6088 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6089 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6092 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6093 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6095 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6097 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6099 ResultRegs[0] =
Lo.getReg(0);
6100 ResultRegs[1] =
Hi.getReg(0);
6103 case TargetOpcode::G_LSHR:
6104 case TargetOpcode::G_ASHR: {
6106 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6108 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6109 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6110 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6114 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6117 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6118 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6120 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6124 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6126 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6128 ResultRegs[0] =
Lo.getReg(0);
6129 ResultRegs[1] =
Hi.getReg(0);
6136 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6137 MI.eraseFromParent();
6146 LLT TargetTy,
LLT ShiftAmtTy) {
6149 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6151 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6152 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6153 const bool NeedsInterWordShift = ShiftBits != 0;
6156 case TargetOpcode::G_SHL: {
6159 if (PartIdx < ShiftWords)
6162 unsigned SrcIdx = PartIdx - ShiftWords;
6163 if (!NeedsInterWordShift)
6164 return SrcParts[SrcIdx];
6169 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6173 return Hi.getReg(0);
6176 case TargetOpcode::G_LSHR: {
6177 unsigned SrcIdx = PartIdx + ShiftWords;
6178 if (SrcIdx >= NumParts)
6180 if (!NeedsInterWordShift)
6181 return SrcParts[SrcIdx];
6185 if (SrcIdx + 1 < NumParts) {
6186 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6190 return Lo.getReg(0);
6193 case TargetOpcode::G_ASHR: {
6195 unsigned SrcIdx = PartIdx + ShiftWords;
6196 if (SrcIdx >= NumParts)
6198 if (!NeedsInterWordShift)
6199 return SrcParts[SrcIdx];
6204 (SrcIdx == NumParts - 1)
6208 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6230 unsigned MainOpcode =
6231 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6235 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6244 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6245 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6247 auto IsZeroBitShift =
6255 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6256 : TargetOpcode::G_SHL;
6259 auto TargetBitsConst =
6261 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6266 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6271 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6273 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6277 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6290 LLT DstTy = MRI.getType(DstReg);
6294 const unsigned NumParts = DstBits / TargetBits;
6296 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6306 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6307 MI.eraseFromParent();
6312 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6313 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6319 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6323 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6326 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6327 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6331 for (
unsigned I = 0;
I < NumParts; ++
I)
6333 Params, TargetTy, ShiftAmtTy);
6335 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6336 MI.eraseFromParent();
6345 LLT DstTy = MRI.getType(DstReg);
6346 LLT ShiftAmtTy = MRI.getType(AmtReg);
6350 const unsigned NumParts = DstBits / TargetBits;
6352 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6369 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6381 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6382 auto TargetBitsLog2Const =
6383 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6384 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6387 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6389 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6397 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6398 auto TargetBitsMinusOneConst =
6399 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6401 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6402 TargetBitsMinusOneConst)
6405 FillValue = ZeroReg;
6413 for (
unsigned I = 0;
I < NumParts; ++
I) {
6415 Register InBoundsResult = FillValue;
6425 for (
unsigned K = 0; K < NumParts; ++K) {
6426 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6428 WordShift, WordShiftKConst);
6440 switch (
MI.getOpcode()) {
6441 case TargetOpcode::G_SHL:
6442 MainSrcIdx = (int)
I - (
int)K;
6443 CarrySrcIdx = MainSrcIdx - 1;
6445 case TargetOpcode::G_LSHR:
6446 case TargetOpcode::G_ASHR:
6447 MainSrcIdx = (int)
I + (
int)K;
6448 CarrySrcIdx = MainSrcIdx + 1;
6456 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6457 Register MainOp = SrcParts[MainSrcIdx];
6461 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6462 CarryOp = SrcParts[CarrySrcIdx];
6463 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6464 CarrySrcIdx >= (
int)NumParts)
6465 CarryOp = FillValue;
6471 ResultForK = FillValue;
6477 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6484 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6488 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6489 MI.eraseFromParent();
6496 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6499 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6514 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6519 "getNeutralElementForVecReduce called with invalid opcode!");
6520 case TargetOpcode::G_VECREDUCE_ADD:
6521 case TargetOpcode::G_VECREDUCE_OR:
6522 case TargetOpcode::G_VECREDUCE_XOR:
6523 case TargetOpcode::G_VECREDUCE_UMAX:
6525 case TargetOpcode::G_VECREDUCE_MUL:
6527 case TargetOpcode::G_VECREDUCE_AND:
6528 case TargetOpcode::G_VECREDUCE_UMIN:
6531 case TargetOpcode::G_VECREDUCE_SMAX:
6534 case TargetOpcode::G_VECREDUCE_SMIN:
6537 case TargetOpcode::G_VECREDUCE_FADD:
6539 case TargetOpcode::G_VECREDUCE_FMUL:
6541 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6542 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6543 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6544 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6552 unsigned Opc =
MI.getOpcode();
6554 case TargetOpcode::G_IMPLICIT_DEF:
6555 case TargetOpcode::G_LOAD: {
6563 case TargetOpcode::G_STORE:
6570 case TargetOpcode::G_AND:
6571 case TargetOpcode::G_OR:
6572 case TargetOpcode::G_XOR:
6573 case TargetOpcode::G_ADD:
6574 case TargetOpcode::G_SUB:
6575 case TargetOpcode::G_MUL:
6576 case TargetOpcode::G_FADD:
6577 case TargetOpcode::G_FSUB:
6578 case TargetOpcode::G_FMUL:
6579 case TargetOpcode::G_FDIV:
6580 case TargetOpcode::G_FCOPYSIGN:
6581 case TargetOpcode::G_UADDSAT:
6582 case TargetOpcode::G_USUBSAT:
6583 case TargetOpcode::G_SADDSAT:
6584 case TargetOpcode::G_SSUBSAT:
6585 case TargetOpcode::G_SMIN:
6586 case TargetOpcode::G_SMAX:
6587 case TargetOpcode::G_UMIN:
6588 case TargetOpcode::G_UMAX:
6589 case TargetOpcode::G_FMINNUM:
6590 case TargetOpcode::G_FMAXNUM:
6591 case TargetOpcode::G_FMINNUM_IEEE:
6592 case TargetOpcode::G_FMAXNUM_IEEE:
6593 case TargetOpcode::G_FMINIMUM:
6594 case TargetOpcode::G_FMAXIMUM:
6595 case TargetOpcode::G_FMINIMUMNUM:
6596 case TargetOpcode::G_FMAXIMUMNUM:
6597 case TargetOpcode::G_STRICT_FADD:
6598 case TargetOpcode::G_STRICT_FSUB:
6599 case TargetOpcode::G_STRICT_FMUL:
6600 case TargetOpcode::G_SHL:
6601 case TargetOpcode::G_ASHR:
6602 case TargetOpcode::G_LSHR: {
6610 case TargetOpcode::G_FMA:
6611 case TargetOpcode::G_STRICT_FMA:
6612 case TargetOpcode::G_FSHR:
6613 case TargetOpcode::G_FSHL: {
6622 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6623 case TargetOpcode::G_EXTRACT:
6630 case TargetOpcode::G_INSERT:
6631 case TargetOpcode::G_INSERT_VECTOR_ELT:
6632 case TargetOpcode::G_FREEZE:
6633 case TargetOpcode::G_FNEG:
6634 case TargetOpcode::G_FABS:
6635 case TargetOpcode::G_FSQRT:
6636 case TargetOpcode::G_FCEIL:
6637 case TargetOpcode::G_FFLOOR:
6638 case TargetOpcode::G_FNEARBYINT:
6639 case TargetOpcode::G_FRINT:
6640 case TargetOpcode::G_INTRINSIC_ROUND:
6641 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6642 case TargetOpcode::G_INTRINSIC_TRUNC:
6643 case TargetOpcode::G_BITREVERSE:
6644 case TargetOpcode::G_BSWAP:
6645 case TargetOpcode::G_FCANONICALIZE:
6646 case TargetOpcode::G_SEXT_INREG:
6647 case TargetOpcode::G_ABS:
6648 case TargetOpcode::G_CTLZ:
6649 case TargetOpcode::G_CTPOP:
6657 case TargetOpcode::G_SELECT: {
6658 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6660 if (!CondTy.isScalar() ||
6666 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6668 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6673 if (CondTy.isVector())
6683 case TargetOpcode::G_UNMERGE_VALUES:
6685 case TargetOpcode::G_PHI:
6687 case TargetOpcode::G_SHUFFLE_VECTOR:
6689 case TargetOpcode::G_BUILD_VECTOR: {
6691 for (
auto Op :
MI.uses()) {
6699 MIRBuilder.buildDeleteTrailingVectorElements(
6700 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6701 MI.eraseFromParent();
6704 case TargetOpcode::G_SEXT:
6705 case TargetOpcode::G_ZEXT:
6706 case TargetOpcode::G_ANYEXT:
6707 case TargetOpcode::G_TRUNC:
6708 case TargetOpcode::G_FPTRUNC:
6709 case TargetOpcode::G_FPEXT:
6710 case TargetOpcode::G_FPTOSI:
6711 case TargetOpcode::G_FPTOUI:
6712 case TargetOpcode::G_FPTOSI_SAT:
6713 case TargetOpcode::G_FPTOUI_SAT:
6714 case TargetOpcode::G_SITOFP:
6715 case TargetOpcode::G_UITOFP: {
6723 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6727 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6735 case TargetOpcode::G_ICMP:
6736 case TargetOpcode::G_FCMP: {
6745 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6750 case TargetOpcode::G_BITCAST: {
6754 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6755 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6771 case TargetOpcode::G_VECREDUCE_FADD:
6772 case TargetOpcode::G_VECREDUCE_FMUL:
6773 case TargetOpcode::G_VECREDUCE_ADD:
6774 case TargetOpcode::G_VECREDUCE_MUL:
6775 case TargetOpcode::G_VECREDUCE_AND:
6776 case TargetOpcode::G_VECREDUCE_OR:
6777 case TargetOpcode::G_VECREDUCE_XOR:
6778 case TargetOpcode::G_VECREDUCE_SMAX:
6779 case TargetOpcode::G_VECREDUCE_SMIN:
6780 case TargetOpcode::G_VECREDUCE_UMAX:
6781 case TargetOpcode::G_VECREDUCE_UMIN: {
6782 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6784 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6785 auto NeutralElement = getNeutralElementForVecReduce(
6791 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6792 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6793 NeutralElement, Idx);
6797 MO.
setReg(NewVec.getReg(0));
6809 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6811 unsigned MaskNumElts = Mask.size();
6812 unsigned SrcNumElts = SrcTy.getNumElements();
6815 if (MaskNumElts == SrcNumElts)
6818 if (MaskNumElts < SrcNumElts) {
6826 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6827 MI.getOperand(1).getReg(),
6828 MI.getOperand(2).getReg(), NewMask);
6829 MI.eraseFromParent();
6834 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6835 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6843 MOps1[0] =
MI.getOperand(1).getReg();
6844 MOps2[0] =
MI.getOperand(2).getReg();
6846 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6847 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6851 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6853 if (Idx >=
static_cast<int>(SrcNumElts))
6854 Idx += PaddedMaskNumElts - SrcNumElts;
6859 if (MaskNumElts != PaddedMaskNumElts) {
6861 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6864 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6866 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6871 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6874 MI.eraseFromParent();
6880 unsigned int TypeIdx,
LLT MoreTy) {
6881 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6883 unsigned NumElts = DstTy.getNumElements();
6886 if (DstTy.isVector() && Src1Ty.isVector() &&
6887 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6895 if (DstTy != Src1Ty || DstTy != Src2Ty)
6903 for (
unsigned I = 0;
I != NumElts; ++
I) {
6905 if (Idx <
static_cast<int>(NumElts))
6908 NewMask[
I] = Idx - NumElts + WidenNumElts;
6912 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6913 MI.getOperand(1).getReg(),
6914 MI.getOperand(2).getReg(), NewMask);
6915 MI.eraseFromParent();
6924 unsigned SrcParts = Src1Regs.
size();
6925 unsigned DstParts = DstRegs.
size();
6927 unsigned DstIdx = 0;
6929 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
6930 DstRegs[DstIdx] = FactorSum;
6935 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
6937 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
6938 i <= std::min(DstIdx, SrcParts - 1); ++i) {
6940 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
6944 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
6945 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
6947 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
6957 if (DstIdx != DstParts - 1) {
6958 MachineInstrBuilder Uaddo =
6959 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
6960 FactorSum = Uaddo.
getReg(0);
6961 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
6962 for (
unsigned i = 2; i < Factors.
size(); ++i) {
6963 MachineInstrBuilder Uaddo =
6964 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
6965 FactorSum = Uaddo.
getReg(0);
6966 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
6967 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
6971 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
6972 for (
unsigned i = 2; i < Factors.
size(); ++i)
6973 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
6976 CarrySumPrevDstIdx = CarrySum;
6977 DstRegs[DstIdx] = FactorSum;
6989 LLT DstType = MRI.getType(DstReg);
6991 if (DstType.isVector())
6994 unsigned Opcode =
MI.getOpcode();
6995 unsigned OpO, OpE, OpF;
6997 case TargetOpcode::G_SADDO:
6998 case TargetOpcode::G_SADDE:
6999 case TargetOpcode::G_UADDO:
7000 case TargetOpcode::G_UADDE:
7001 case TargetOpcode::G_ADD:
7002 OpO = TargetOpcode::G_UADDO;
7003 OpE = TargetOpcode::G_UADDE;
7004 OpF = TargetOpcode::G_UADDE;
7005 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7006 OpF = TargetOpcode::G_SADDE;
7008 case TargetOpcode::G_SSUBO:
7009 case TargetOpcode::G_SSUBE:
7010 case TargetOpcode::G_USUBO:
7011 case TargetOpcode::G_USUBE:
7012 case TargetOpcode::G_SUB:
7013 OpO = TargetOpcode::G_USUBO;
7014 OpE = TargetOpcode::G_USUBE;
7015 OpF = TargetOpcode::G_USUBE;
7016 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7017 OpF = TargetOpcode::G_SSUBE;
7024 unsigned NumDefs =
MI.getNumExplicitDefs();
7025 Register Src1 =
MI.getOperand(NumDefs).getReg();
7026 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7029 CarryDst =
MI.getOperand(1).getReg();
7030 if (
MI.getNumOperands() == NumDefs + 3)
7031 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7033 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7034 LLT LeftoverTy, DummyTy;
7036 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7041 int NarrowParts = Src1Regs.
size();
7042 Src1Regs.
append(Src1Left);
7043 Src2Regs.
append(Src2Left);
7046 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7048 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7051 if (i == e - 1 && CarryDst)
7052 CarryOut = CarryDst;
7054 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7057 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7058 {Src1Regs[i], Src2Regs[i]});
7059 }
else if (i == e - 1) {
7060 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7061 {Src1Regs[i], Src2Regs[i], CarryIn});
7063 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7064 {Src1Regs[i], Src2Regs[i], CarryIn});
7070 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7071 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7072 ArrayRef(DstRegs).drop_front(NarrowParts));
7074 MI.eraseFromParent();
7080 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7082 LLT Ty = MRI.getType(DstReg);
7086 unsigned Size = Ty.getSizeInBits();
7088 if (
Size % NarrowSize != 0)
7091 unsigned NumParts =
Size / NarrowSize;
7092 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7093 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7099 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7103 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7104 MI.eraseFromParent();
7114 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7117 LLT SrcTy = MRI.getType(Src);
7128 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7141 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7144 if (SizeOp1 % NarrowSize != 0)
7146 int NumParts = SizeOp1 / NarrowSize;
7149 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7153 uint64_t OpStart =
MI.getOperand(2).getImm();
7154 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7155 for (
int i = 0; i < NumParts; ++i) {
7156 unsigned SrcStart = i * NarrowSize;
7158 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7161 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7169 int64_t ExtractOffset;
7171 if (OpStart < SrcStart) {
7173 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7175 ExtractOffset = OpStart - SrcStart;
7176 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7180 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7182 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7183 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7190 if (MRI.getType(DstReg).isVector())
7191 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7192 else if (DstRegs.
size() > 1)
7193 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7196 MI.eraseFromParent();
7208 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7210 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7213 SrcRegs.
append(LeftoverRegs);
7217 uint64_t OpStart =
MI.getOperand(3).getImm();
7218 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7219 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7220 unsigned DstStart =
I * NarrowSize;
7222 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7230 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7232 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7236 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7244 int64_t ExtractOffset, InsertOffset;
7246 if (OpStart < DstStart) {
7248 ExtractOffset = DstStart - OpStart;
7249 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7251 InsertOffset = OpStart - DstStart;
7254 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7258 if (ExtractOffset != 0 || SegSize != OpSize) {
7260 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7261 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7264 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7265 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7273 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7276 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7278 MI.eraseFromParent();
7286 LLT DstTy = MRI.getType(DstReg);
7288 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7294 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7295 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7299 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7300 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7303 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7304 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7305 {Src0Regs[I], Src1Regs[I]});
7309 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7312 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7313 DstLeftoverRegs.
push_back(Inst.getReg(0));
7316 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7317 LeftoverTy, DstLeftoverRegs);
7319 MI.eraseFromParent();
7329 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7331 LLT DstTy = MRI.getType(DstReg);
7336 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7337 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7338 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7340 MI.eraseFromParent();
7350 Register CondReg =
MI.getOperand(1).getReg();
7351 LLT CondTy = MRI.getType(CondReg);
7356 LLT DstTy = MRI.getType(DstReg);
7362 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7363 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7367 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7368 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7371 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7373 CondReg, Src1Regs[
I], Src2Regs[
I]);
7377 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7379 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7383 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7384 LeftoverTy, DstLeftoverRegs);
7386 MI.eraseFromParent();
7396 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7399 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7400 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7403 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7405 auto C_0 =
B.buildConstant(NarrowTy, 0);
7407 UnmergeSrc.getReg(1), C_0);
7408 auto LoCTLZ = IsUndef ?
7409 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7410 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7411 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7412 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7413 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7414 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7416 MI.eraseFromParent();
7429 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7432 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7433 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7436 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7438 auto C_0 =
B.buildConstant(NarrowTy, 0);
7440 UnmergeSrc.getReg(0), C_0);
7441 auto HiCTTZ = IsUndef ?
7442 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7443 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7444 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7445 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7446 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7447 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7449 MI.eraseFromParent();
7462 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7465 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7466 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7468 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7469 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7470 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7472 MI.eraseFromParent();
7487 LLT ExpTy = MRI.getType(ExpReg);
7492 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7493 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7494 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7495 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7497 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7499 MI.getOperand(2).setReg(Trunc.getReg(0));
7506 unsigned Opc =
MI.getOpcode();
7509 auto QAction = LI.getAction(Q).Action;
7515 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7518 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7522 case TargetOpcode::G_CTLZ: {
7523 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7524 unsigned Len = SrcTy.getSizeInBits();
7526 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7528 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7529 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7532 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7533 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7534 MI.eraseFromParent();
7550 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7551 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7554 Op = MIBOp.getReg(0);
7559 MI.eraseFromParent();
7562 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7565 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7569 case TargetOpcode::G_CTTZ: {
7570 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7572 unsigned Len = SrcTy.getSizeInBits();
7573 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7576 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7577 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7580 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7581 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7582 MI.eraseFromParent();
7589 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7590 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7592 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7593 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7594 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7595 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7598 MI.eraseFromParent();
7602 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7603 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7607 case TargetOpcode::G_CTPOP: {
7609 LLT Ty = MRI.getType(SrcReg);
7610 unsigned Size = Ty.getSizeInBits();
7618 auto C_1 =
B.buildConstant(Ty, 1);
7619 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7621 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7622 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7623 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7627 auto C_2 =
B.buildConstant(Ty, 2);
7628 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7630 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7631 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7632 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7633 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7640 auto C_4 =
B.buildConstant(Ty, 4);
7641 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7642 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7644 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7645 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7647 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7653 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7655 auto IsMulSupported = [
this](
const LLT Ty) {
7656 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7659 if (IsMulSupported(Ty)) {
7660 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7661 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7663 auto ResTmp = B8Count;
7664 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7665 auto ShiftC =
B.buildConstant(Ty, Shift);
7666 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7667 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7669 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7671 MI.eraseFromParent();
7692 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7693 LLT Ty = MRI.getType(Dst);
7694 LLT ShTy = MRI.getType(Z);
7701 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7702 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7707 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7708 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7712 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7725 MI.eraseFromParent();
7731 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7732 LLT Ty = MRI.getType(Dst);
7733 LLT ShTy = MRI.getType(Z);
7736 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7746 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7747 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7748 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7749 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7750 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7754 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7757 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7760 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7762 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7763 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7764 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7767 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7769 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7771 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7774 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7775 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7780 MI.eraseFromParent();
7791 LLT Ty = MRI.getType(Dst);
7792 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7794 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7795 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7798 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7799 return lowerFunnelShiftAsShifts(
MI);
7803 if (Result == UnableToLegalize)
7804 return lowerFunnelShiftAsShifts(
MI);
7809 auto [Dst, Src] =
MI.getFirst2Regs();
7810 LLT DstTy = MRI.getType(Dst);
7811 LLT SrcTy = MRI.getType(Src);
7815 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7823 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7827 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7831 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7836 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7837 {UnmergeSrc.getReg(0)});
7838 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7839 {UnmergeSrc.getReg(1)});
7842 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7844 MI.eraseFromParent();
7861 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7865 LLT DstTy = MRI.getType(DstReg);
7866 LLT SrcTy = MRI.getType(SrcReg);
7874 SrcTy.getElementCount().divideCoefficientBy(2));
7887 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7899 MI.eraseFromParent();
7908 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7909 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
7910 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7911 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7912 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
7913 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
7914 MI.eraseFromParent();
7919 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7921 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
7922 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7927 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7928 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
7930 return lowerRotateWithReverseRotate(
MI);
7933 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7934 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7935 bool IsFShLegal =
false;
7936 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
7937 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
7941 MI.eraseFromParent();
7946 return buildFunnelShift(FShOpc, Dst, Src, Amt);
7949 return buildFunnelShift(RevFsh, Dst, Src, Amt);
7954 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
7955 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
7956 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
7962 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
7963 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
7965 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
7971 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
7972 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
7974 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
7976 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
7980 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
7981 MI.eraseFromParent();
7989 auto [Dst, Src] =
MI.getFirst2Regs();
7994 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8022 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8035 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8039 MI.eraseFromParent();
8047 auto [Dst, Src] =
MI.getFirst2Regs();
8052 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8065 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8067 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8072 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8074 MI.eraseFromParent();
8082 auto [Dst, Src] =
MI.getFirst2Regs();
8086 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8097 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8098 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8100 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8107 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8108 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8109 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8111 MI.eraseFromParent();
8121 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8127 MI.eraseFromParent();
8132 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8135 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8136 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8137 MIRBuilder.buildSelect(Dst, Src, True, False);
8138 MI.eraseFromParent();
8142 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8162 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8169 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8170 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8171 MIRBuilder.buildSelect(Dst, Src, True, False);
8172 MI.eraseFromParent();
8176 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8199 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8200 MI.eraseFromParent();
8208 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8212 if (SrcTy !=
S64 && SrcTy !=
S32)
8214 if (DstTy !=
S32 && DstTy !=
S64)
8241 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8243 MI.eraseFromParent();
8248 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8253 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8260 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8262 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8263 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8265 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8266 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8268 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8270 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8271 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8272 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8275 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8276 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8277 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8279 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8282 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8287 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8288 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8294 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8296 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8297 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8299 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8304 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8305 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8307 MI.eraseFromParent();
8313 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8315 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8316 unsigned SatWidth = DstTy.getScalarSizeInBits();
8320 APInt MinInt, MaxInt;
8343 if (AreExactFloatBounds) {
8345 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8347 SrcTy.changeElementSize(1), Src, MaxC);
8348 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8350 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8360 MI.eraseFromParent();
8365 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8367 DstTy.changeElementSize(1), Src, Src);
8370 MI.eraseFromParent();
8377 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8386 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8397 MI.eraseFromParent();
8403 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8405 DstTy.changeElementSize(1), Src, Src);
8407 MI.eraseFromParent();
8417 auto [Dst, Src] =
MI.getFirst2Regs();
8419 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8421 if (MRI.getType(Src).isVector())
8425 unsigned Flags =
MI.getFlags();
8428 MI.eraseFromParent();
8432 const unsigned ExpMask = 0x7ff;
8433 const unsigned ExpBiasf64 = 1023;
8434 const unsigned ExpBiasf16 = 15;
8463 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8523 MI.eraseFromParent();
8529 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8533 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8540 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8541 LLT Ty = MRI.getType(Dst);
8543 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8544 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8545 MI.eraseFromParent();
8551 case TargetOpcode::G_SMIN:
8553 case TargetOpcode::G_SMAX:
8555 case TargetOpcode::G_UMIN:
8557 case TargetOpcode::G_UMAX:
8565 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8570 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8571 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8573 MI.eraseFromParent();
8582 LLT DstTy = MRI.getType(Dst);
8583 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8593 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8594 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8596 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8599 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8600 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8603 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8604 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8606 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8607 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8613 unsigned BoolExtOp =
8615 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8616 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8620 MI.eraseFromParent();
8626 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8627 const int Src0Size = Src0Ty.getScalarSizeInBits();
8628 const int Src1Size = Src1Ty.getScalarSizeInBits();
8633 auto NotSignBitMask =
MIRBuilder.buildConstant(
8638 if (Src0Ty == Src1Ty) {
8639 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8640 }
else if (Src0Size > Src1Size) {
8641 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8642 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8643 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8644 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8646 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8647 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8648 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8649 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8655 unsigned Flags =
MI.getFlags();
8662 MI.eraseFromParent();
8673 switch (
MI.getOpcode()) {
8674 case TargetOpcode::G_FMINNUM:
8675 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8677 case TargetOpcode::G_FMINIMUMNUM:
8678 NewOp = TargetOpcode::G_FMINNUM;
8680 case TargetOpcode::G_FMAXNUM:
8681 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8683 case TargetOpcode::G_FMAXIMUMNUM:
8684 NewOp = TargetOpcode::G_FMAXNUM;
8690 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8691 LLT Ty = MRI.getType(Dst);
8701 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8704 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8709 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8710 MI.eraseFromParent();
8717 LLT Ty = MRI.getType(DstReg);
8718 unsigned Flags =
MI.getFlags();
8723 MI.eraseFromParent();
8729 auto [DstReg,
X] =
MI.getFirst2Regs();
8730 const unsigned Flags =
MI.getFlags();
8731 const LLT Ty = MRI.getType(DstReg);
8743 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8745 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8750 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8751 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8752 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8753 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8755 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8757 MI.eraseFromParent();
8762 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8763 unsigned Flags =
MI.getFlags();
8764 LLT Ty = MRI.getType(DstReg);
8771 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8772 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8775 SrcReg, Zero, Flags);
8777 SrcReg, Trunc, Flags);
8781 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8782 MI.eraseFromParent();
8788 const unsigned NumOps =
MI.getNumOperands();
8789 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8790 unsigned PartSize = Src0Ty.getSizeInBits();
8795 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8796 const unsigned Offset = (
I - 1) * PartSize;
8799 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8802 MRI.createGenericVirtualRegister(WideTy);
8805 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8806 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8807 ResultReg = NextResult;
8810 if (DstTy.isPointer()) {
8811 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8812 DstTy.getAddressSpace())) {
8820 MI.eraseFromParent();
8826 const unsigned NumDst =
MI.getNumOperands() - 1;
8827 Register SrcReg =
MI.getOperand(NumDst).getReg();
8828 Register Dst0Reg =
MI.getOperand(0).getReg();
8829 LLT DstTy = MRI.getType(Dst0Reg);
8838 LLT IntTy = MRI.getType(SrcReg);
8843 unsigned Offset = DstSize;
8844 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
8846 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
8850 MI.eraseFromParent();
8869 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
8870 InsertVal =
MI.getOperand(2).getReg();
8872 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
8874 LLT VecTy = MRI.getType(SrcVec);
8884 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
8885 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
8887 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
8890 MI.eraseFromParent();
8895 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
8906 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
8913 int64_t
Offset = IdxVal * EltBytes;
8924 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
8927 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
8929 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
8932 MI.eraseFromParent();
8938 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
8939 MI.getFirst3RegLLTs();
8947 for (
int Idx : Mask) {
8949 if (!Undef.isValid())
8950 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
8955 if (Src0Ty.isScalar()) {
8956 BuildVec.
push_back(Idx == 0 ? Src0Reg : Src1Reg);
8958 int NumElts = Src0Ty.getNumElements();
8959 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
8960 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
8961 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
8962 auto Extract =
MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK);
8967 if (DstTy.isVector())
8968 MIRBuilder.buildBuildVector(DstReg, BuildVec);
8971 MI.eraseFromParent();
8977 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
8978 MI.getFirst4RegLLTs();
8980 if (VecTy.isScalableVector())
8996 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
8999 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9002 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9005 std::optional<APInt> PassthruSplatVal =
9008 if (PassthruSplatVal.has_value()) {
9010 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9011 }
else if (HasPassthru) {
9012 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9013 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9019 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9023 unsigned NumElmts = VecTy.getNumElements();
9024 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9026 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9029 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9032 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9037 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9039 if (HasPassthru &&
I == NumElmts - 1) {
9042 auto AllLanesSelected =
MIRBuilder.buildICmp(
9044 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9045 {OutPos, EndOfVector});
9049 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9051 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9056 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9058 MI.eraseFromParent();
9069 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9075 if (Alignment >
Align(1)) {
9078 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9087 const auto &MF = *
MI.getMF();
9093 Register AllocSize =
MI.getOperand(1).getReg();
9096 LLT PtrTy = MRI.getType(Dst);
9097 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9104 MI.eraseFromParent();
9110 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9115 MI.eraseFromParent();
9121 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9126 MI.eraseFromParent();
9132 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9133 unsigned Offset =
MI.getOperand(2).getImm();
9136 if (SrcTy.isVector()) {
9137 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9138 unsigned DstSize = DstTy.getSizeInBits();
9140 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9141 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9143 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9147 for (
unsigned Idx =
Offset / SrcEltSize;
9148 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9149 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9151 if (SubVectorElts.
size() == 1)
9152 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9154 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9156 MI.eraseFromParent();
9161 if (DstTy.isScalar() &&
9162 (SrcTy.isScalar() ||
9163 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9164 LLT SrcIntTy = SrcTy;
9165 if (!SrcTy.isScalar()) {
9167 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9174 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9178 MI.eraseFromParent();
9186 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9189 LLT DstTy = MRI.getType(Src);
9190 LLT InsertTy = MRI.getType(InsertSrc);
9198 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9200 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9204 for (; Idx <
Offset / EltSize; ++Idx) {
9205 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9210 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9211 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9213 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9222 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9225 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9226 MI.eraseFromParent();
9240 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9244 LLT IntDstTy = DstTy;
9248 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9253 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9259 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9265 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9266 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9267 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9270 MI.eraseFromParent();
9276 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9277 MI.getFirst4RegLLTs();
9278 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9281 LLT BoolTy = Dst1Ty;
9283 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9300 auto ResultLowerThanLHS =
9305 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9308 MI.eraseFromParent();
9314 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9315 const LLT Ty = MRI.getType(Res);
9318 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9319 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9320 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9331 MI.eraseFromParent();
9336 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9337 const LLT Ty = MRI.getType(Res);
9340 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9341 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9342 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9347 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9352 MI.eraseFromParent();
9358 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9359 LLT Ty = MRI.getType(Res);
9363 switch (
MI.getOpcode()) {
9366 case TargetOpcode::G_UADDSAT:
9369 BaseOp = TargetOpcode::G_ADD;
9371 case TargetOpcode::G_SADDSAT:
9374 BaseOp = TargetOpcode::G_ADD;
9376 case TargetOpcode::G_USUBSAT:
9379 BaseOp = TargetOpcode::G_SUB;
9381 case TargetOpcode::G_SSUBSAT:
9384 BaseOp = TargetOpcode::G_SUB;
9399 uint64_t NumBits = Ty.getScalarSizeInBits();
9410 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9418 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9423 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9424 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9427 MI.eraseFromParent();
9433 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9434 LLT Ty = MRI.getType(Res);
9438 unsigned OverflowOp;
9439 switch (
MI.getOpcode()) {
9442 case TargetOpcode::G_UADDSAT:
9445 OverflowOp = TargetOpcode::G_UADDO;
9447 case TargetOpcode::G_SADDSAT:
9450 OverflowOp = TargetOpcode::G_SADDO;
9452 case TargetOpcode::G_USUBSAT:
9455 OverflowOp = TargetOpcode::G_USUBO;
9457 case TargetOpcode::G_SSUBSAT:
9460 OverflowOp = TargetOpcode::G_SSUBO;
9465 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9466 Register Tmp = OverflowRes.getReg(0);
9467 Register Ov = OverflowRes.getReg(1);
9476 uint64_t NumBits = Ty.getScalarSizeInBits();
9477 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9478 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9481 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9489 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9493 MI.eraseFromParent();
9499 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9500 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9501 "Expected shlsat opcode!");
9502 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9503 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9504 LLT Ty = MRI.getType(Res);
9508 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9509 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9518 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9523 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9525 MI.eraseFromParent();
9530 auto [Dst, Src] =
MI.getFirst2Regs();
9531 const LLT Ty = MRI.getType(Src);
9532 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9533 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9536 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9537 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9538 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9539 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9542 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9544 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9545 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9546 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9548 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9549 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9550 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9552 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9553 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9554 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9556 Res.getInstr()->getOperand(0).setReg(Dst);
9558 MI.eraseFromParent();
9565 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9568 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9569 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9570 return B.buildOr(Dst,
LHS,
RHS);
9575 auto [Dst, Src] =
MI.getFirst2Regs();
9576 const LLT SrcTy = MRI.getType(Src);
9577 unsigned Size = SrcTy.getScalarSizeInBits();
9578 unsigned VSize = SrcTy.getSizeInBits();
9581 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9582 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9583 {LLT::fixed_vector(VSize / 8, 8),
9584 LLT::fixed_vector(VSize / 8, 8)}}))) {
9589 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9590 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9591 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9595 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9618 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9622 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9625 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9629 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9633 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9638 MI.eraseFromParent();
9646 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9647 int NameOpIdx = IsRead ? 1 : 0;
9648 int ValRegIndex = IsRead ? 0 : 1;
9650 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9651 const LLT Ty = MRI.getType(ValReg);
9653 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9660 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9661 Fn,
MI.getDebugLoc()));
9665 MI.eraseFromParent();
9674 MI.eraseFromParent();
9680 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9681 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9683 LLT OrigTy = MRI.getType(Result);
9687 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9688 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9690 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9692 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9693 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9696 MI.eraseFromParent();
9702 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9707 MI.eraseFromParent();
9712 MI.eraseFromParent();
9719 unsigned BitSize = SrcTy.getScalarSizeInBits();
9723 if (SrcTy.isVector())
9724 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9725 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9731 APInt ExpMask = Inf;
9737 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9738 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9739 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9740 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9741 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9743 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9747 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9749 LLT DstTyCopy = DstTy;
9751 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9779 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9782 Mask &= ~PartialCheck;
9791 else if (PartialCheck ==
fcZero)
9803 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9804 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9807 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9809 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9810 appendToRes(SubnormalRes);
9817 else if (PartialCheck ==
fcInf)
9822 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9829 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
9830 if (PartialCheck ==
fcNan) {
9834 }
else if (PartialCheck ==
fcQNan) {
9844 Abs, InfWithQnanBitC);
9845 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
9852 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
9854 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
9855 APInt MaxExpMinusOne = ExpMask - ExpLSB;
9858 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
9860 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
9863 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
9864 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
9866 appendToRes(NormalRes);
9870 MI.eraseFromParent();
9876 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
9877 MI.getFirst4RegLLTs();
9879 bool IsEltPtr = DstTy.isPointerOrPointerVector();
9883 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
9884 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
9888 if (MaskTy.isScalar()) {
9896 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
9900 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
9902 if (DstTy.isVector()) {
9904 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
9905 MaskReg = ShufSplat.getReg(0);
9910 }
else if (!DstTy.isVector()) {
9915 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
9919 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
9920 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
9921 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
9928 MI.eraseFromParent();
9934 unsigned Opcode =
MI.getOpcode();
9937 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
9938 : TargetOpcode::G_UDIV,
9939 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9941 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
9942 : TargetOpcode::G_UREM,
9943 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9944 MI.eraseFromParent();
9954 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
9958 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
9961 MI.eraseFromParent();
9972 LLT Ty = MRI.getType(SrcReg);
9976 MI.eraseFromParent();
9983 Register DestReg =
MI.getOperand(0).getReg();
9985 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
9989 MI.eraseFromParent();
9995 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
9996 MI.getOpcode() == TargetOpcode::G_ABDU) &&
9997 "Expected G_ABDS or G_ABDU instruction");
9999 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10000 LLT Ty = MRI.getType(LHS);
10010 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10012 MI.eraseFromParent();
10018 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10019 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10020 "Expected G_ABDS or G_ABDU instruction");
10022 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10023 LLT Ty = MRI.getType(LHS);
10028 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10029 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10030 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10032 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10033 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10035 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10037 MI.eraseFromParent();
10042 Register SrcReg =
MI.getOperand(1).getReg();
10043 Register DstReg =
MI.getOperand(0).getReg();
10045 LLT Ty = MRI.getType(DstReg);
10053 MI.eraseFromParent();
10059 Register SrcReg =
MI.getOperand(1).getReg();
10060 LLT SrcTy = MRI.getType(SrcReg);
10061 LLT DstTy = MRI.getType(SrcReg);
10064 if (SrcTy.isScalar()) {
10069 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10080 Register ListPtr =
MI.getOperand(1).getReg();
10081 LLT PtrTy = MRI.getType(ListPtr);
10088 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10090 const Align A(
MI.getOperand(2).getImm());
10092 if (
A > TLI.getMinStackArgumentAlignment()) {
10094 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10095 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10096 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10097 VAList = AndDst.getReg(0);
10104 LLT LLTTy = MRI.getType(Dst);
10107 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10108 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10113 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10115 Align EltAlignment =
DL.getABITypeAlign(Ty);
10118 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10120 MI.eraseFromParent();
10135 unsigned Limit,
const MemOp &
Op,
10136 unsigned DstAS,
unsigned SrcAS,
10137 const AttributeList &FuncAttributes,
10139 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10149 if (
Op.isFixedDstAlign())
10150 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10153 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10157 unsigned NumMemOps = 0;
10160 unsigned TySize = Ty.getSizeInBytes();
10161 while (TySize >
Size) {
10170 assert(NewTySize > 0 &&
"Could not find appropriate type");
10177 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10179 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10185 TySize = NewTySize;
10189 if (++NumMemOps > Limit)
10192 MemOps.push_back(Ty);
10202 unsigned NumBits = Ty.getScalarSizeInBits();
10204 if (!Ty.isVector() && ValVRegAndVal) {
10205 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10213 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10234 uint64_t KnownLen,
Align Alignment,
10236 auto &MF = *
MI.getParent()->getParent();
10241 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10243 bool DstAlignCanChange =
false;
10247 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10249 DstAlignCanChange =
true;
10251 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10252 std::vector<LLT> MemOps;
10254 const auto &DstMMO = **
MI.memoperands_begin();
10255 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10258 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10269 if (DstAlignCanChange) {
10272 Align NewAlign =
DL.getABITypeAlign(IRTy);
10273 if (NewAlign > Alignment) {
10274 Alignment = NewAlign;
10282 MachineIRBuilder MIB(
MI);
10284 LLT LargestTy = MemOps[0];
10285 for (
unsigned i = 1; i < MemOps.size(); i++)
10287 LargestTy = MemOps[i];
10299 LLT PtrTy = MRI.getType(Dst);
10300 unsigned DstOff = 0;
10301 unsigned Size = KnownLen;
10302 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10303 LLT Ty = MemOps[
I];
10305 if (TySize >
Size) {
10308 assert(
I == MemOps.size() - 1 &&
I != 0);
10309 DstOff -= TySize -
Size;
10319 TLI.isTruncateFree(LargestVT, VT))
10320 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10333 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10336 MIB.buildStore(
Value,
Ptr, *StoreMMO);
10341 MI.eraseFromParent();
10347 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10349 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10351 const auto *MMOIt =
MI.memoperands_begin();
10353 bool IsVolatile =
MemOp->isVolatile();
10359 "inline memcpy with dynamic size is not yet supported");
10360 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10361 if (KnownLen == 0) {
10362 MI.eraseFromParent();
10366 const auto &DstMMO = **
MI.memoperands_begin();
10367 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10368 Align DstAlign = DstMMO.getBaseAlign();
10369 Align SrcAlign = SrcMMO.getBaseAlign();
10371 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10378 Align SrcAlign,
bool IsVolatile) {
10379 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10380 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10381 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10388 Align SrcAlign,
bool IsVolatile) {
10389 auto &MF = *
MI.getParent()->getParent();
10394 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10396 bool DstAlignCanChange =
false;
10398 Align Alignment = std::min(DstAlign, SrcAlign);
10402 DstAlignCanChange =
true;
10408 std::vector<LLT> MemOps;
10410 const auto &DstMMO = **
MI.memoperands_begin();
10411 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10417 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10423 if (DstAlignCanChange) {
10426 Align NewAlign =
DL.getABITypeAlign(IRTy);
10431 if (!
TRI->hasStackRealignment(MF))
10433 NewAlign = std::min(NewAlign, *StackAlign);
10435 if (NewAlign > Alignment) {
10436 Alignment = NewAlign;
10444 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10446 MachineIRBuilder MIB(
MI);
10452 unsigned CurrOffset = 0;
10453 unsigned Size = KnownLen;
10454 for (
auto CopyTy : MemOps) {
10457 if (CopyTy.getSizeInBytes() >
Size)
10458 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10469 if (CurrOffset != 0) {
10470 LLT SrcTy = MRI.getType(Src);
10473 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10475 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10479 if (CurrOffset != 0) {
10480 LLT DstTy = MRI.getType(Dst);
10481 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10483 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10484 CurrOffset += CopyTy.getSizeInBytes();
10485 Size -= CopyTy.getSizeInBytes();
10488 MI.eraseFromParent();
10494 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10496 auto &MF = *
MI.getParent()->getParent();
10501 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10503 bool DstAlignCanChange =
false;
10506 Align Alignment = std::min(DstAlign, SrcAlign);
10508 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10510 DstAlignCanChange =
true;
10512 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10513 std::vector<LLT> MemOps;
10515 const auto &DstMMO = **
MI.memoperands_begin();
10516 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10517 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10518 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10525 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10531 if (DstAlignCanChange) {
10534 Align NewAlign =
DL.getABITypeAlign(IRTy);
10539 if (!
TRI->hasStackRealignment(MF))
10540 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10541 NewAlign = std::min(NewAlign, *StackAlign);
10543 if (NewAlign > Alignment) {
10544 Alignment = NewAlign;
10552 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10554 MachineIRBuilder MIB(
MI);
10558 unsigned CurrOffset = 0;
10559 SmallVector<Register, 16> LoadVals;
10560 for (
auto CopyTy : MemOps) {
10567 if (CurrOffset != 0) {
10568 LLT SrcTy = MRI.getType(Src);
10571 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10573 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10574 CurrOffset += CopyTy.getSizeInBytes();
10578 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10579 LLT CopyTy = MemOps[
I];
10585 if (CurrOffset != 0) {
10586 LLT DstTy = MRI.getType(Dst);
10589 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10591 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10594 MI.eraseFromParent();
10600 const unsigned Opc =
MI.getOpcode();
10603 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10604 Opc == TargetOpcode::G_MEMSET) &&
10605 "Expected memcpy like instruction");
10607 auto MMOIt =
MI.memoperands_begin();
10612 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10614 if (
Opc != TargetOpcode::G_MEMSET) {
10615 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10616 MemOp = *(++MMOIt);
10617 SrcAlign =
MemOp->getBaseAlign();
10622 if (!LenVRegAndVal)
10624 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10626 if (KnownLen == 0) {
10627 MI.eraseFromParent();
10631 if (MaxLen && KnownLen > MaxLen)
10634 bool IsVolatile =
MemOp->isVolatile();
10635 if (
Opc == TargetOpcode::G_MEMCPY) {
10636 auto &MF = *
MI.getParent()->getParent();
10639 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10640 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10643 if (
Opc == TargetOpcode::G_MEMMOVE)
10644 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10645 if (
Opc == TargetOpcode::G_MEMSET)
10646 return lowerMemset(
MI, Dst, Src, KnownLen, DstAlign, IsVolatile);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static bool findGISelOptimalMemOpLowering(std::vector< LLT > &MemOps, unsigned Limit, const MemOp &Op, unsigned DstAS, unsigned SrcAS, const AttributeList &FuncAttributes, const TargetLowering &TLI)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static LegalizerHelper::LegalizeResult conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, Type *FromType, LostDebugLocObserver &LocObserver, const TargetLowering &TLI, bool IsSigned=false)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static LegalizerHelper::LegalizeResult simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver)
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static bool shouldLowerMemFuncForSize(const MachineFunction &MF)
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static LegalizerHelper::LegalizeResult createAtomicLibcall(MachineIRBuilder &MIRBuilder, MachineInstr &MI)
static RTLIB::Libcall getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI)
static std::pair< int, int > getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy)
Try to break down OrigTy into NarrowTy sized pieces.
static bool hasSameNumEltsOnAllVectorOperands(GenericMachineInstr &MI, MachineRegisterInfo &MRI, std::initializer_list< unsigned > NonVecOpIndices)
Check that all vector operands have same number of elements.
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg, LLT VecTy)
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, Type *FromType)
static void getUnmergeResults(SmallVectorImpl< Register > &Regs, const MachineInstr &MI)
Append the result registers of G_UNMERGE_VALUES MI to Regs.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
#define RTLIBCASE(LibcallPrefix)
static Type * getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Tracks DebugLocs between checkpoints and verifies that they are transferred.
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file describes how to lower LLVM code to machine code.
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.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
void negate()
Negate this APInt in place.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, unsigned hiBit)
Wrap version of getBitsSet.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Represents a insert subvector.
Register getSubVec() const
Register getBigVec() const
uint64_t getIndexImm() const
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
Represents a threeway compare.
Register getValueReg() const
Get the stored value register.
A base class for all GenericMachineInstrs.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr ElementCount getElementCount() const
constexpr LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr LLT getScalarType() const
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerThreewayCompare(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI)
LLVM_ABI LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI)
Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
LLVM_ABI LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty)
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSSUBE(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerSMULH_UMULH(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerLoad(GAnyLoad &MI)
LLVM_ABI LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerAbsToAddXor(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerFConstant(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerBitreverse(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
Legalize a vector instruction by increasing the number of vector elements involved and ignoring the a...
LLVM_ABI LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy)
Multi-way shift legalization: directly split wide shifts into target-sized parts in a single step,...
LLVM_ABI LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI)
LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI Register buildConstantShiftPart(unsigned Opcode, unsigned PartIdx, unsigned NumParts, ArrayRef< Register > SrcParts, const ShiftParams &Params, LLT TargetTy, LLT ShiftAmtTy)
Generates a single output part for constant shifts using direct indexing.
LLVM_ABI void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by truncating the operand's ty...
LLVM_ABI LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI, unsigned NumElts)
LLVM_ABI LegalizeResult lowerFPTOUI(MachineInstr &MI)
const TargetLowering & getTargetLowering() const
LLVM_ABI LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
LLVM_ABI LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult bitcastInsertSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_INSERT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult lowerUnmergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by replacing the value type.
LLVM_ABI LegalizeResult scalarizeVectorBooleanStore(GStore &MI)
Given a store of a boolean vector, scalarize it.
LLVM_ABI LegalizeResult lowerBitcast(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerReadWriteRegister(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, LLT HalfTy, LLT ShiftAmtTy)
LLVM_ABI LegalizeResult lowerISFPCLASS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFAbs(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerVectorReduction(MachineInstr &MI)
const LegalizerInfo & getLegalizerInfo() const
Expose LegalizerInfo so the clients can re-use.
LLVM_ABI LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult fewerElementsVectorMultiEltType(GenericMachineInstr &MI, unsigned NumElts, std::initializer_list< unsigned > NonVecOpIndices={})
Handles most opcodes.
LLVM_ABI LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarShiftByConstantMultiway(MachineInstr &MI, const APInt &Amt, LLT TargetTy, LLT ShiftAmtTy)
Optimized path for constant shift amounts using static indexing.
LLVM_ABI MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val)
Create a store of Val to a stack temporary and return a load as the same type as Res.
LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ AlreadyLegal
Instruction was already legal and no change was made to the MachineFunction.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFCopySign(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B)
LLVM_ABI LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSADDE(MachineInstr &MI)
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
LLVM_ABI LegalizeResult lowerFunnelShift(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFPTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
LLVM_ABI LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
LLVM_ABI LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerFFloor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult fewerElementsVectorSeqReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize, Align Alignment, LLT PtrTy)
LLVM_ABI LegalizeResult lowerFPTOSI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerUITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerShuffleVector(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerMergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerVECTOR_COMPRESS(MachineInstr &MI)
LLVM_ABI void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by producing a vector with und...
LLVM_ABI LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF32WithSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0)
LLVM_ABI Register coerceToScalar(Register Val)
Cast the given value to an LLT::scalar with an equivalent size.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI LegalizeResult lowerTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBswap(MachineInstr &MI)
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
LLVM_ABI LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const
Return the alignment to use for a stack temporary object with the given type.
LLVM_ABI LegalizeResult lowerConstant(MachineInstr &MI)
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LLVM_ABI LegalizeResult legalizeInstrStep(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Replace MI by a sequence of legal instructions that can implement the same operation.
TypeSize getValue() const
void checkpoint(bool CheckDebugLocs=true)
Call this to indicate that it's a good point to assess whether locations have been lost.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
LLVM_ABI StringRef getString() const
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
LLVM_ABI iterator getFirstTerminatorForward()
Finds the first terminator in a block by scanning forward.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_UREM Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0)
Build and insert integer negation Zero = G_CONSTANT 0 Res = G_SUB Zero, Op0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_UITOFP Src0.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
MachineInstrBuilder buildXor(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_XOR Op0, Op1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
virtual bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *=nullptr) const
Determine if the target supports unaligned memory accesses.
virtual LLT getOptimalMemOpLLT(const MemOp &Op, const AttributeList &) const
LLT returning variant.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const
Returns true if arguments should be sign-extended in lib calls.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
const Triple & getTargetTriple() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const CallLowering * getCallLowering() const
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, DriverKit, XROS, or bridgeOS).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Type * getType() const
All values are typed, get the type of this value.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ Custom
The target wants to do something special with this combination of operand and type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
FunctionAddr VTableAddr Value
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
LLVM_ABI LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver)
Create a libcall to memcpy et al.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI LegalizerHelper::LegalizeResult createLibcall(MachineIRBuilder &MIRBuilder, const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr)
Helper function that creates a libcall to the given Name using the given calling convention CC.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI)
Returns true if Val can be assumed to never be a signaling NaN.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static LLVM_ABI const fltSemantics & IEEEsingle() LLVM_READNONE
static constexpr roundingMode rmNearestTiesToEven
static constexpr roundingMode rmTowardZero
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE
opStatus
IEEE-754R 7: Default exception handling.
This struct is a compact representation of a valid (non-zero power of two) alignment.
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.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
static MemOp Set(uint64_t Size, bool DstAlignCanChange, Align DstAlign, bool IsZeroMemset, bool IsVolatile)
static MemOp Copy(uint64_t Size, bool DstAlignCanChange, Align DstAlign, Align SrcAlign, bool IsVolatile, bool MemcpyStrSrc=false)