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_UMULH:
4461 case TargetOpcode::G_SMULH:
4463 case TargetOpcode::G_SMULO:
4464 case TargetOpcode::G_UMULO: {
4467 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4468 LLT Ty = MRI.getType(Res);
4470 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4471 ? TargetOpcode::G_SMULH
4472 : TargetOpcode::G_UMULH;
4476 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4477 MI.removeOperand(1);
4480 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4488 if (Opcode == TargetOpcode::G_SMULH) {
4489 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4490 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4497 case TargetOpcode::G_FNEG: {
4498 auto [Res, SubByReg] =
MI.getFirst2Regs();
4499 LLT Ty = MRI.getType(Res);
4503 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4504 MI.eraseFromParent();
4507 case TargetOpcode::G_FSUB:
4508 case TargetOpcode::G_STRICT_FSUB: {
4509 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4510 LLT Ty = MRI.getType(Res);
4515 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4516 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4520 MI.eraseFromParent();
4523 case TargetOpcode::G_FMAD:
4525 case TargetOpcode::G_FFLOOR:
4527 case TargetOpcode::G_LROUND:
4528 case TargetOpcode::G_LLROUND: {
4531 LLT SrcTy = MRI.getType(SrcReg);
4532 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4535 MI.eraseFromParent();
4538 case TargetOpcode::G_INTRINSIC_ROUND:
4540 case TargetOpcode::G_FRINT: {
4543 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4546 case TargetOpcode::G_INTRINSIC_LRINT:
4547 case TargetOpcode::G_INTRINSIC_LLRINT: {
4550 LLT SrcTy = MRI.getType(SrcReg);
4552 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4554 MI.eraseFromParent();
4557 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4558 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4559 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4560 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4561 **
MI.memoperands_begin());
4563 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4564 MI.eraseFromParent();
4567 case TargetOpcode::G_LOAD:
4568 case TargetOpcode::G_SEXTLOAD:
4569 case TargetOpcode::G_ZEXTLOAD:
4571 case TargetOpcode::G_STORE:
4573 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4574 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4575 case TargetOpcode::G_CTLZ:
4576 case TargetOpcode::G_CTTZ:
4577 case TargetOpcode::G_CTPOP:
4580 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4582 Register NewRes = MRI.cloneVirtualRegister(Res);
4589 MI.eraseFromParent();
4593 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4594 const LLT CondTy = MRI.getType(CarryOut);
4595 const LLT Ty = MRI.getType(Res);
4597 Register NewRes = MRI.cloneVirtualRegister(Res);
4600 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4606 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4607 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4614 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4619 MI.eraseFromParent();
4623 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4628 MI.eraseFromParent();
4632 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4633 const LLT CondTy = MRI.getType(BorrowOut);
4634 const LLT Ty = MRI.getType(Res);
4637 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4643 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4644 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4651 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4652 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4654 MI.eraseFromParent();
4687 case G_MERGE_VALUES:
4689 case G_UNMERGE_VALUES:
4691 case TargetOpcode::G_SEXT_INREG: {
4692 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4693 int64_t SizeInBits =
MI.getOperand(2).getImm();
4695 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4696 LLT DstTy = MRI.getType(DstReg);
4697 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4700 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4701 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4702 MI.eraseFromParent();
4705 case G_EXTRACT_VECTOR_ELT:
4706 case G_INSERT_VECTOR_ELT:
4708 case G_SHUFFLE_VECTOR:
4710 case G_VECTOR_COMPRESS:
4712 case G_DYN_STACKALLOC:
4716 case G_STACKRESTORE:
4726 case G_READ_REGISTER:
4727 case G_WRITE_REGISTER:
4734 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4735 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4741 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4746 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4757 bool IsSigned =
MI.getOpcode() == G_ABDS;
4758 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4759 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4760 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4784 case G_MEMCPY_INLINE:
4785 return lowerMemcpyInline(
MI);
4796 case G_ATOMICRMW_SUB: {
4797 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4798 const LLT ValTy = MRI.getType(Val);
4802 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4803 MI.eraseFromParent();
4826 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4830 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4836 Align StackTypeAlign =
4843 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4844 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4849 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4861 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4864 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4875 "Converting bits to bytes lost precision");
4881 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4882 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4884 if (IdxTy != MRI.getType(Index))
4885 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4890 LLT PtrTy = MRI.getType(VecPtr);
4891 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4899 std::initializer_list<unsigned> NonVecOpIndices) {
4900 if (
MI.getNumMemOperands() != 0)
4903 LLT VecTy =
MRI.getType(
MI.getReg(0));
4917 if (!Ty.isVector()) {
4923 if (Ty.getNumElements() != NumElts)
4938 assert(Ty.isVector() &&
"Expected vector type");
4941 int NumParts, NumLeftover;
4942 std::tie(NumParts, NumLeftover) =
4945 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
4946 for (
int i = 0; i < NumParts; ++i) {
4951 assert(NumLeftover == 1 &&
"expected exactly one leftover");
4960 for (
unsigned i = 0; i <
N; ++i) {
4962 Ops.push_back(
Op.getReg());
4963 else if (
Op.isImm())
4964 Ops.push_back(
Op.getImm());
4965 else if (
Op.isPredicate())
4987 std::initializer_list<unsigned> NonVecOpIndices) {
4989 "Non-compatible opcode or not specified non-vector operands");
4990 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
4992 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
4993 unsigned NumDefs =
MI.getNumDefs();
5001 for (
unsigned i = 0; i < NumDefs; ++i) {
5002 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5010 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5011 ++UseIdx, ++UseNo) {
5014 MI.getOperand(UseIdx));
5023 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5027 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5029 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5030 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5033 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5034 Uses.push_back(InputOpsPieces[InputNo][i]);
5037 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5038 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5043 for (
unsigned i = 0; i < NumDefs; ++i)
5044 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5046 for (
unsigned i = 0; i < NumDefs; ++i)
5047 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5050 MI.eraseFromParent();
5057 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5059 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5060 unsigned NumDefs =
MI.getNumDefs();
5064 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5069 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5070 UseIdx += 2, ++UseNo) {
5078 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5080 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5081 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5083 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5086 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5087 Phi.addUse(InputOpsPieces[j][i]);
5088 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5098 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5100 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5103 MI.eraseFromParent();
5111 const int NumDst =
MI.getNumOperands() - 1;
5112 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5113 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5114 LLT SrcTy = MRI.getType(SrcReg);
5116 if (TypeIdx != 1 || NarrowTy == DstTy)
5123 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5126 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5140 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5141 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5142 const int PartsPerUnmerge = NumDst / NumUnmerge;
5144 for (
int I = 0;
I != NumUnmerge; ++
I) {
5145 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5147 for (
int J = 0; J != PartsPerUnmerge; ++J)
5148 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5149 MIB.addUse(Unmerge.getReg(
I));
5152 MI.eraseFromParent();
5159 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5163 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5165 if (NarrowTy == SrcTy)
5173 assert(SrcTy.isVector() &&
"Expected vector types");
5175 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5189 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5190 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5191 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5197 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5198 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5199 ++i,
Offset += NumNarrowTyElts) {
5202 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5205 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5206 MI.eraseFromParent();
5210 assert(TypeIdx == 0 &&
"Bad type index");
5211 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5226 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5227 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5229 for (
unsigned i = 0; i < NumParts; ++i) {
5231 for (
unsigned j = 0; j < NumElts; ++j)
5232 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5234 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5237 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5238 MI.eraseFromParent();
5246 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5248 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5250 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5252 InsertVal =
MI.getOperand(2).getReg();
5254 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5255 LLT VecTy = MRI.getType(SrcVec);
5261 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5265 MI.eraseFromParent();
5274 SplitPieces[IdxVal] = InsertVal;
5275 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5277 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5281 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5284 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5285 TargetOpcode::G_ANYEXT);
5289 LLT IdxTy = MRI.getType(Idx);
5290 int64_t PartIdx = IdxVal / NewNumElts;
5292 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5295 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5298 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5299 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5300 VecParts[PartIdx] = InsertPart.getReg(0);
5304 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5306 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5310 MI.eraseFromParent();
5330 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5342 LLT ValTy = MRI.getType(ValReg);
5351 int NumLeftover = -1;
5357 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5359 NumParts = NarrowRegs.
size();
5360 NumLeftover = NarrowLeftoverRegs.
size();
5367 LLT PtrTy = MRI.getType(AddrReg);
5370 unsigned TotalSize = ValTy.getSizeInBits();
5377 auto MMO = LdStMI.
getMMO();
5379 unsigned NumParts,
unsigned Offset) ->
unsigned {
5382 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5384 unsigned ByteOffset =
Offset / 8;
5387 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5394 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5395 ValRegs.push_back(Dst);
5396 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5398 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5407 unsigned HandledOffset =
5408 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5412 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5415 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5416 LeftoverTy, NarrowLeftoverRegs);
5430 switch (
MI.getOpcode()) {
5431 case G_IMPLICIT_DEF:
5447 case G_FCANONICALIZE:
5464 case G_INTRINSIC_LRINT:
5465 case G_INTRINSIC_LLRINT:
5466 case G_INTRINSIC_ROUND:
5467 case G_INTRINSIC_ROUNDEVEN:
5470 case G_INTRINSIC_TRUNC:
5497 case G_FMINNUM_IEEE:
5498 case G_FMAXNUM_IEEE:
5520 case G_CTLZ_ZERO_UNDEF:
5522 case G_CTTZ_ZERO_UNDEF:
5538 case G_ADDRSPACE_CAST:
5551 case G_STRICT_FLDEXP:
5560 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5565 case G_UNMERGE_VALUES:
5567 case G_BUILD_VECTOR:
5568 assert(TypeIdx == 0 &&
"not a vector type index");
5570 case G_CONCAT_VECTORS:
5574 case G_EXTRACT_VECTOR_ELT:
5575 case G_INSERT_VECTOR_ELT:
5584 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5585 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5587 case G_SHUFFLE_VECTOR:
5593 case G_INTRINSIC_FPTRUNC_ROUND:
5603 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5604 "Not a bitcast operation");
5609 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5611 unsigned NewElemCount =
5614 if (NewElemCount == 1) {
5617 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5623 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5632 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5633 MI.eraseFromParent();
5639 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5643 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5644 MI.getFirst3RegLLTs();
5647 if (DstTy != Src1Ty)
5649 if (DstTy != Src2Ty)
5664 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5680 unsigned InputUsed[2] = {-1U, -1U};
5681 unsigned FirstMaskIdx =
High * NewElts;
5682 bool UseBuildVector =
false;
5683 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5685 int Idx = Mask[FirstMaskIdx + MaskOffset];
5690 if (
Input >= std::size(Inputs)) {
5697 Idx -=
Input * NewElts;
5701 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5702 if (InputUsed[OpNo] ==
Input) {
5705 }
else if (InputUsed[OpNo] == -1U) {
5707 InputUsed[OpNo] =
Input;
5712 if (OpNo >= std::size(InputUsed)) {
5715 UseBuildVector =
true;
5720 Ops.push_back(Idx + OpNo * NewElts);
5723 if (UseBuildVector) {
5728 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5730 int Idx = Mask[FirstMaskIdx + MaskOffset];
5735 if (
Input >= std::size(Inputs)) {
5742 Idx -=
Input * NewElts;
5746 .buildExtractVectorElement(
5747 EltTy, Inputs[
Input],
5753 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5754 }
else if (InputUsed[0] == -1U) {
5756 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5758 Register Op0 = Inputs[InputUsed[0]];
5762 : Inputs[InputUsed[1]];
5764 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5771 MI.eraseFromParent();
5784 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5790 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5793 const unsigned NumParts =
5795 : SrcTy.getNumElements();
5799 if (DstTy != NarrowTy)
5805 unsigned NumPartsLeft = NumParts;
5806 while (NumPartsLeft > 1) {
5807 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5810 .buildInstr(ScalarOpc, {NarrowTy},
5811 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5814 SplitSrcs = PartialResults;
5815 PartialResults.
clear();
5816 NumPartsLeft = SplitSrcs.
size();
5820 MI.eraseFromParent();
5825 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5826 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5829 MI.eraseFromParent();
5833 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5835 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5843 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5846 Register Acc = PartialReductions[0];
5847 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5848 if (Part == NumParts - 1) {
5850 {Acc, PartialReductions[Part]});
5853 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5857 MI.eraseFromParent();
5863 unsigned int TypeIdx,
5865 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5866 MI.getFirst3RegLLTs();
5867 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5871 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5872 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5873 "Unexpected vecreduce opcode");
5874 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5875 ? TargetOpcode::G_FADD
5876 : TargetOpcode::G_FMUL;
5879 unsigned NumParts = SrcTy.getNumElements();
5882 for (
unsigned i = 0; i < NumParts; i++)
5883 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5887 MI.eraseFromParent();
5894 unsigned ScalarOpc) {
5902 while (SplitSrcs.
size() > 1) {
5904 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
5912 SplitSrcs = std::move(PartialRdxs);
5916 MI.getOperand(1).setReg(SplitSrcs[0]);
5923 const LLT HalfTy,
const LLT AmtTy) {
5925 Register InL = MRI.createGenericVirtualRegister(HalfTy);
5926 Register InH = MRI.createGenericVirtualRegister(HalfTy);
5930 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
5931 MI.eraseFromParent();
5937 unsigned VTBits = 2 * NVTBits;
5940 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
5941 if (Amt.
ugt(VTBits)) {
5943 }
else if (Amt.
ugt(NVTBits)) {
5946 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5947 }
else if (Amt == NVTBits) {
5955 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5958 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
5959 if (Amt.
ugt(VTBits)) {
5961 }
else if (Amt.
ugt(NVTBits)) {
5963 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5965 }
else if (Amt == NVTBits) {
5969 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
5971 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
5973 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5979 if (Amt.
ugt(VTBits)) {
5981 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5982 }
else if (Amt.
ugt(NVTBits)) {
5984 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5986 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5987 }
else if (Amt == NVTBits) {
5990 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5992 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
5994 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
5996 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6003 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6004 MI.eraseFromParent();
6020 LLT DstTy = MRI.getType(DstReg);
6025 LLT ShiftAmtTy = MRI.getType(Amt);
6027 if (DstEltSize % 2 != 0)
6043 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6054 const unsigned NewBitSize = DstEltSize / 2;
6066 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6068 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6069 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6072 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6073 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6075 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6080 switch (
MI.getOpcode()) {
6081 case TargetOpcode::G_SHL: {
6083 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6085 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6086 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6087 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6090 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6091 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6093 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6095 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6097 ResultRegs[0] =
Lo.getReg(0);
6098 ResultRegs[1] =
Hi.getReg(0);
6101 case TargetOpcode::G_LSHR:
6102 case TargetOpcode::G_ASHR: {
6104 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6106 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6107 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6108 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6112 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6115 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6116 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6118 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6122 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6124 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6126 ResultRegs[0] =
Lo.getReg(0);
6127 ResultRegs[1] =
Hi.getReg(0);
6134 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6135 MI.eraseFromParent();
6144 LLT TargetTy,
LLT ShiftAmtTy) {
6147 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6149 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6150 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6151 const bool NeedsInterWordShift = ShiftBits != 0;
6154 case TargetOpcode::G_SHL: {
6157 if (PartIdx < ShiftWords)
6160 unsigned SrcIdx = PartIdx - ShiftWords;
6161 if (!NeedsInterWordShift)
6162 return SrcParts[SrcIdx];
6167 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6171 return Hi.getReg(0);
6174 case TargetOpcode::G_LSHR: {
6175 unsigned SrcIdx = PartIdx + ShiftWords;
6176 if (SrcIdx >= NumParts)
6178 if (!NeedsInterWordShift)
6179 return SrcParts[SrcIdx];
6183 if (SrcIdx + 1 < NumParts) {
6184 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6188 return Lo.getReg(0);
6191 case TargetOpcode::G_ASHR: {
6193 unsigned SrcIdx = PartIdx + ShiftWords;
6194 if (SrcIdx >= NumParts)
6196 if (!NeedsInterWordShift)
6197 return SrcParts[SrcIdx];
6202 (SrcIdx == NumParts - 1)
6206 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6228 unsigned MainOpcode =
6229 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6233 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6242 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6243 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6245 auto IsZeroBitShift =
6253 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6254 : TargetOpcode::G_SHL;
6257 auto TargetBitsConst =
6259 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6264 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6269 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6271 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6275 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6288 LLT DstTy = MRI.getType(DstReg);
6292 const unsigned NumParts = DstBits / TargetBits;
6294 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6304 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6305 MI.eraseFromParent();
6310 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6311 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6317 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6321 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6324 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6325 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6329 for (
unsigned I = 0;
I < NumParts; ++
I)
6331 Params, TargetTy, ShiftAmtTy);
6333 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6334 MI.eraseFromParent();
6343 LLT DstTy = MRI.getType(DstReg);
6344 LLT ShiftAmtTy = MRI.getType(AmtReg);
6348 const unsigned NumParts = DstBits / TargetBits;
6350 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6367 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6379 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6380 auto TargetBitsLog2Const =
6381 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6382 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6385 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6387 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6395 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6396 auto TargetBitsMinusOneConst =
6397 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6399 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6400 TargetBitsMinusOneConst)
6403 FillValue = ZeroReg;
6411 for (
unsigned I = 0;
I < NumParts; ++
I) {
6413 Register InBoundsResult = FillValue;
6423 for (
unsigned K = 0; K < NumParts; ++K) {
6424 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6426 WordShift, WordShiftKConst);
6438 switch (
MI.getOpcode()) {
6439 case TargetOpcode::G_SHL:
6440 MainSrcIdx = (int)
I - (
int)K;
6441 CarrySrcIdx = MainSrcIdx - 1;
6443 case TargetOpcode::G_LSHR:
6444 case TargetOpcode::G_ASHR:
6445 MainSrcIdx = (int)
I + (
int)K;
6446 CarrySrcIdx = MainSrcIdx + 1;
6454 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6455 Register MainOp = SrcParts[MainSrcIdx];
6459 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6460 CarryOp = SrcParts[CarrySrcIdx];
6461 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6462 CarrySrcIdx >= (
int)NumParts)
6463 CarryOp = FillValue;
6469 ResultForK = FillValue;
6475 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6482 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6486 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6487 MI.eraseFromParent();
6494 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6497 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6512 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6517 "getNeutralElementForVecReduce called with invalid opcode!");
6518 case TargetOpcode::G_VECREDUCE_ADD:
6519 case TargetOpcode::G_VECREDUCE_OR:
6520 case TargetOpcode::G_VECREDUCE_XOR:
6521 case TargetOpcode::G_VECREDUCE_UMAX:
6523 case TargetOpcode::G_VECREDUCE_MUL:
6525 case TargetOpcode::G_VECREDUCE_AND:
6526 case TargetOpcode::G_VECREDUCE_UMIN:
6529 case TargetOpcode::G_VECREDUCE_SMAX:
6532 case TargetOpcode::G_VECREDUCE_SMIN:
6535 case TargetOpcode::G_VECREDUCE_FADD:
6537 case TargetOpcode::G_VECREDUCE_FMUL:
6539 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6540 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6541 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6542 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6550 unsigned Opc =
MI.getOpcode();
6552 case TargetOpcode::G_IMPLICIT_DEF:
6553 case TargetOpcode::G_LOAD: {
6561 case TargetOpcode::G_STORE:
6568 case TargetOpcode::G_AND:
6569 case TargetOpcode::G_OR:
6570 case TargetOpcode::G_XOR:
6571 case TargetOpcode::G_ADD:
6572 case TargetOpcode::G_SUB:
6573 case TargetOpcode::G_MUL:
6574 case TargetOpcode::G_FADD:
6575 case TargetOpcode::G_FSUB:
6576 case TargetOpcode::G_FMUL:
6577 case TargetOpcode::G_FDIV:
6578 case TargetOpcode::G_FCOPYSIGN:
6579 case TargetOpcode::G_UADDSAT:
6580 case TargetOpcode::G_USUBSAT:
6581 case TargetOpcode::G_SADDSAT:
6582 case TargetOpcode::G_SSUBSAT:
6583 case TargetOpcode::G_SMIN:
6584 case TargetOpcode::G_SMAX:
6585 case TargetOpcode::G_UMIN:
6586 case TargetOpcode::G_UMAX:
6587 case TargetOpcode::G_FMINNUM:
6588 case TargetOpcode::G_FMAXNUM:
6589 case TargetOpcode::G_FMINNUM_IEEE:
6590 case TargetOpcode::G_FMAXNUM_IEEE:
6591 case TargetOpcode::G_FMINIMUM:
6592 case TargetOpcode::G_FMAXIMUM:
6593 case TargetOpcode::G_FMINIMUMNUM:
6594 case TargetOpcode::G_FMAXIMUMNUM:
6595 case TargetOpcode::G_STRICT_FADD:
6596 case TargetOpcode::G_STRICT_FSUB:
6597 case TargetOpcode::G_STRICT_FMUL:
6598 case TargetOpcode::G_SHL:
6599 case TargetOpcode::G_ASHR:
6600 case TargetOpcode::G_LSHR: {
6608 case TargetOpcode::G_FMA:
6609 case TargetOpcode::G_STRICT_FMA:
6610 case TargetOpcode::G_FSHR:
6611 case TargetOpcode::G_FSHL: {
6620 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6621 case TargetOpcode::G_EXTRACT:
6628 case TargetOpcode::G_INSERT:
6629 case TargetOpcode::G_INSERT_VECTOR_ELT:
6630 case TargetOpcode::G_FREEZE:
6631 case TargetOpcode::G_FNEG:
6632 case TargetOpcode::G_FABS:
6633 case TargetOpcode::G_FSQRT:
6634 case TargetOpcode::G_FCEIL:
6635 case TargetOpcode::G_FFLOOR:
6636 case TargetOpcode::G_FNEARBYINT:
6637 case TargetOpcode::G_FRINT:
6638 case TargetOpcode::G_INTRINSIC_ROUND:
6639 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6640 case TargetOpcode::G_INTRINSIC_TRUNC:
6641 case TargetOpcode::G_BITREVERSE:
6642 case TargetOpcode::G_BSWAP:
6643 case TargetOpcode::G_FCANONICALIZE:
6644 case TargetOpcode::G_SEXT_INREG:
6645 case TargetOpcode::G_ABS:
6646 case TargetOpcode::G_CTLZ:
6647 case TargetOpcode::G_CTPOP:
6655 case TargetOpcode::G_SELECT: {
6656 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6658 if (!CondTy.isScalar() ||
6664 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6666 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6671 if (CondTy.isVector())
6681 case TargetOpcode::G_UNMERGE_VALUES:
6683 case TargetOpcode::G_PHI:
6685 case TargetOpcode::G_SHUFFLE_VECTOR:
6687 case TargetOpcode::G_BUILD_VECTOR: {
6689 for (
auto Op :
MI.uses()) {
6697 MIRBuilder.buildDeleteTrailingVectorElements(
6698 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6699 MI.eraseFromParent();
6702 case TargetOpcode::G_SEXT:
6703 case TargetOpcode::G_ZEXT:
6704 case TargetOpcode::G_ANYEXT:
6705 case TargetOpcode::G_TRUNC:
6706 case TargetOpcode::G_FPTRUNC:
6707 case TargetOpcode::G_FPEXT:
6708 case TargetOpcode::G_FPTOSI:
6709 case TargetOpcode::G_FPTOUI:
6710 case TargetOpcode::G_FPTOSI_SAT:
6711 case TargetOpcode::G_FPTOUI_SAT:
6712 case TargetOpcode::G_SITOFP:
6713 case TargetOpcode::G_UITOFP: {
6721 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6725 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6733 case TargetOpcode::G_ICMP:
6734 case TargetOpcode::G_FCMP: {
6743 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6748 case TargetOpcode::G_BITCAST: {
6752 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6753 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6769 case TargetOpcode::G_VECREDUCE_FADD:
6770 case TargetOpcode::G_VECREDUCE_FMUL:
6771 case TargetOpcode::G_VECREDUCE_ADD:
6772 case TargetOpcode::G_VECREDUCE_MUL:
6773 case TargetOpcode::G_VECREDUCE_AND:
6774 case TargetOpcode::G_VECREDUCE_OR:
6775 case TargetOpcode::G_VECREDUCE_XOR:
6776 case TargetOpcode::G_VECREDUCE_SMAX:
6777 case TargetOpcode::G_VECREDUCE_SMIN:
6778 case TargetOpcode::G_VECREDUCE_UMAX:
6779 case TargetOpcode::G_VECREDUCE_UMIN: {
6780 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6782 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6783 auto NeutralElement = getNeutralElementForVecReduce(
6789 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6790 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6791 NeutralElement, Idx);
6795 MO.
setReg(NewVec.getReg(0));
6807 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6809 unsigned MaskNumElts = Mask.size();
6810 unsigned SrcNumElts = SrcTy.getNumElements();
6813 if (MaskNumElts == SrcNumElts)
6816 if (MaskNumElts < SrcNumElts) {
6824 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6825 MI.getOperand(1).getReg(),
6826 MI.getOperand(2).getReg(), NewMask);
6827 MI.eraseFromParent();
6832 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6833 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6841 MOps1[0] =
MI.getOperand(1).getReg();
6842 MOps2[0] =
MI.getOperand(2).getReg();
6844 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6845 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6849 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6851 if (Idx >=
static_cast<int>(SrcNumElts))
6852 Idx += PaddedMaskNumElts - SrcNumElts;
6857 if (MaskNumElts != PaddedMaskNumElts) {
6859 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6862 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6864 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6869 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6872 MI.eraseFromParent();
6878 unsigned int TypeIdx,
LLT MoreTy) {
6879 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6881 unsigned NumElts = DstTy.getNumElements();
6884 if (DstTy.isVector() && Src1Ty.isVector() &&
6885 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6893 if (DstTy != Src1Ty || DstTy != Src2Ty)
6901 for (
unsigned I = 0;
I != NumElts; ++
I) {
6903 if (Idx <
static_cast<int>(NumElts))
6906 NewMask[
I] = Idx - NumElts + WidenNumElts;
6910 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6911 MI.getOperand(1).getReg(),
6912 MI.getOperand(2).getReg(), NewMask);
6913 MI.eraseFromParent();
6922 unsigned SrcParts = Src1Regs.
size();
6923 unsigned DstParts = DstRegs.
size();
6925 unsigned DstIdx = 0;
6927 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
6928 DstRegs[DstIdx] = FactorSum;
6933 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
6935 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
6936 i <= std::min(DstIdx, SrcParts - 1); ++i) {
6938 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
6942 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
6943 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
6945 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
6955 if (DstIdx != DstParts - 1) {
6956 MachineInstrBuilder Uaddo =
6957 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
6958 FactorSum = Uaddo.
getReg(0);
6959 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
6960 for (
unsigned i = 2; i < Factors.
size(); ++i) {
6961 MachineInstrBuilder Uaddo =
6962 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
6963 FactorSum = Uaddo.
getReg(0);
6964 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
6965 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
6969 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
6970 for (
unsigned i = 2; i < Factors.
size(); ++i)
6971 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
6974 CarrySumPrevDstIdx = CarrySum;
6975 DstRegs[DstIdx] = FactorSum;
6987 LLT DstType = MRI.getType(DstReg);
6989 if (DstType.isVector())
6992 unsigned Opcode =
MI.getOpcode();
6993 unsigned OpO, OpE, OpF;
6995 case TargetOpcode::G_SADDO:
6996 case TargetOpcode::G_SADDE:
6997 case TargetOpcode::G_UADDO:
6998 case TargetOpcode::G_UADDE:
6999 case TargetOpcode::G_ADD:
7000 OpO = TargetOpcode::G_UADDO;
7001 OpE = TargetOpcode::G_UADDE;
7002 OpF = TargetOpcode::G_UADDE;
7003 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7004 OpF = TargetOpcode::G_SADDE;
7006 case TargetOpcode::G_SSUBO:
7007 case TargetOpcode::G_SSUBE:
7008 case TargetOpcode::G_USUBO:
7009 case TargetOpcode::G_USUBE:
7010 case TargetOpcode::G_SUB:
7011 OpO = TargetOpcode::G_USUBO;
7012 OpE = TargetOpcode::G_USUBE;
7013 OpF = TargetOpcode::G_USUBE;
7014 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7015 OpF = TargetOpcode::G_SSUBE;
7022 unsigned NumDefs =
MI.getNumExplicitDefs();
7023 Register Src1 =
MI.getOperand(NumDefs).getReg();
7024 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7027 CarryDst =
MI.getOperand(1).getReg();
7028 if (
MI.getNumOperands() == NumDefs + 3)
7029 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7031 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7032 LLT LeftoverTy, DummyTy;
7034 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7039 int NarrowParts = Src1Regs.
size();
7040 Src1Regs.
append(Src1Left);
7041 Src2Regs.
append(Src2Left);
7044 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7046 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7049 if (i == e - 1 && CarryDst)
7050 CarryOut = CarryDst;
7052 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7055 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7056 {Src1Regs[i], Src2Regs[i]});
7057 }
else if (i == e - 1) {
7058 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7059 {Src1Regs[i], Src2Regs[i], CarryIn});
7061 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7062 {Src1Regs[i], Src2Regs[i], CarryIn});
7068 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7069 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7070 ArrayRef(DstRegs).drop_front(NarrowParts));
7072 MI.eraseFromParent();
7078 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7080 LLT Ty = MRI.getType(DstReg);
7084 unsigned Size = Ty.getSizeInBits();
7086 if (
Size % NarrowSize != 0)
7089 unsigned NumParts =
Size / NarrowSize;
7090 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7091 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7097 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7101 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7102 MI.eraseFromParent();
7112 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7115 LLT SrcTy = MRI.getType(Src);
7126 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7139 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7142 if (SizeOp1 % NarrowSize != 0)
7144 int NumParts = SizeOp1 / NarrowSize;
7147 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7151 uint64_t OpStart =
MI.getOperand(2).getImm();
7152 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7153 for (
int i = 0; i < NumParts; ++i) {
7154 unsigned SrcStart = i * NarrowSize;
7156 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7159 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7167 int64_t ExtractOffset;
7169 if (OpStart < SrcStart) {
7171 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7173 ExtractOffset = OpStart - SrcStart;
7174 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7178 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7180 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7181 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7188 if (MRI.getType(DstReg).isVector())
7189 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7190 else if (DstRegs.
size() > 1)
7191 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7194 MI.eraseFromParent();
7206 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7208 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7211 SrcRegs.
append(LeftoverRegs);
7215 uint64_t OpStart =
MI.getOperand(3).getImm();
7216 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7217 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7218 unsigned DstStart =
I * NarrowSize;
7220 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7228 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7230 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7234 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7242 int64_t ExtractOffset, InsertOffset;
7244 if (OpStart < DstStart) {
7246 ExtractOffset = DstStart - OpStart;
7247 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7249 InsertOffset = OpStart - DstStart;
7252 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7256 if (ExtractOffset != 0 || SegSize != OpSize) {
7258 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7259 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7262 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7263 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7271 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7274 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7276 MI.eraseFromParent();
7284 LLT DstTy = MRI.getType(DstReg);
7286 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7292 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7293 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7297 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7298 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7301 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7302 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7303 {Src0Regs[I], Src1Regs[I]});
7307 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7310 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7311 DstLeftoverRegs.
push_back(Inst.getReg(0));
7314 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7315 LeftoverTy, DstLeftoverRegs);
7317 MI.eraseFromParent();
7327 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7329 LLT DstTy = MRI.getType(DstReg);
7334 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7335 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7336 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7338 MI.eraseFromParent();
7348 Register CondReg =
MI.getOperand(1).getReg();
7349 LLT CondTy = MRI.getType(CondReg);
7354 LLT DstTy = MRI.getType(DstReg);
7360 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7361 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7365 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7366 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7369 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7371 CondReg, Src1Regs[
I], Src2Regs[
I]);
7375 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7377 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7381 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7382 LeftoverTy, DstLeftoverRegs);
7384 MI.eraseFromParent();
7394 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7397 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7398 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7401 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7403 auto C_0 =
B.buildConstant(NarrowTy, 0);
7405 UnmergeSrc.getReg(1), C_0);
7406 auto LoCTLZ = IsUndef ?
7407 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7408 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7409 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7410 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7411 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7412 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7414 MI.eraseFromParent();
7427 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7430 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7431 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7434 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7436 auto C_0 =
B.buildConstant(NarrowTy, 0);
7438 UnmergeSrc.getReg(0), C_0);
7439 auto HiCTTZ = IsUndef ?
7440 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7441 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7442 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7443 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7444 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7445 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7447 MI.eraseFromParent();
7460 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7463 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7464 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7466 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7467 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7468 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7470 MI.eraseFromParent();
7485 LLT ExpTy = MRI.getType(ExpReg);
7490 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7491 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7492 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7493 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7495 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7497 MI.getOperand(2).setReg(Trunc.getReg(0));
7504 unsigned Opc =
MI.getOpcode();
7507 auto QAction = LI.getAction(Q).Action;
7513 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7516 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7520 case TargetOpcode::G_CTLZ: {
7521 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7522 unsigned Len = SrcTy.getSizeInBits();
7524 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7526 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7527 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7530 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7531 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7532 MI.eraseFromParent();
7548 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7549 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7552 Op = MIBOp.getReg(0);
7557 MI.eraseFromParent();
7560 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7563 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7567 case TargetOpcode::G_CTTZ: {
7568 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7570 unsigned Len = SrcTy.getSizeInBits();
7571 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7574 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7575 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7578 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7579 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7580 MI.eraseFromParent();
7587 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7588 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7590 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7591 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7592 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7593 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7596 MI.eraseFromParent();
7600 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7601 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7605 case TargetOpcode::G_CTPOP: {
7607 LLT Ty = MRI.getType(SrcReg);
7608 unsigned Size = Ty.getSizeInBits();
7616 auto C_1 =
B.buildConstant(Ty, 1);
7617 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7619 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7620 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7621 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7625 auto C_2 =
B.buildConstant(Ty, 2);
7626 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7628 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7629 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7630 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7631 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7638 auto C_4 =
B.buildConstant(Ty, 4);
7639 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7640 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7642 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7643 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7645 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7651 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7653 auto IsMulSupported = [
this](
const LLT Ty) {
7654 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7657 if (IsMulSupported(Ty)) {
7658 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7659 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7661 auto ResTmp = B8Count;
7662 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7663 auto ShiftC =
B.buildConstant(Ty, Shift);
7664 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7665 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7667 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7669 MI.eraseFromParent();
7690 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7691 LLT Ty = MRI.getType(Dst);
7692 LLT ShTy = MRI.getType(Z);
7699 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7700 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7705 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7706 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7710 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7723 MI.eraseFromParent();
7729 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7730 LLT Ty = MRI.getType(Dst);
7731 LLT ShTy = MRI.getType(Z);
7734 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7744 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7745 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7746 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7747 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7748 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7752 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7755 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7758 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7760 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7761 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7762 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7765 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7767 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7769 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7772 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7773 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7778 MI.eraseFromParent();
7789 LLT Ty = MRI.getType(Dst);
7790 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7792 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7793 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7796 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7797 return lowerFunnelShiftAsShifts(
MI);
7801 if (Result == UnableToLegalize)
7802 return lowerFunnelShiftAsShifts(
MI);
7807 auto [Dst, Src] =
MI.getFirst2Regs();
7808 LLT DstTy = MRI.getType(Dst);
7809 LLT SrcTy = MRI.getType(Src);
7813 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7821 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7825 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7829 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7834 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7835 {UnmergeSrc.getReg(0)});
7836 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7837 {UnmergeSrc.getReg(1)});
7840 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7842 MI.eraseFromParent();
7859 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7863 LLT DstTy = MRI.getType(DstReg);
7864 LLT SrcTy = MRI.getType(SrcReg);
7872 SrcTy.getElementCount().divideCoefficientBy(2));
7885 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7897 MI.eraseFromParent();
7906 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7907 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
7908 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7909 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7910 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
7911 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
7912 MI.eraseFromParent();
7917 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7919 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
7920 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7925 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7926 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
7928 return lowerRotateWithReverseRotate(
MI);
7931 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7932 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7933 bool IsFShLegal =
false;
7934 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
7935 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
7939 MI.eraseFromParent();
7944 return buildFunnelShift(FShOpc, Dst, Src, Amt);
7947 return buildFunnelShift(RevFsh, Dst, Src, Amt);
7952 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
7953 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
7954 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
7960 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
7961 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
7963 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
7969 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
7970 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
7972 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
7974 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
7978 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
7979 MI.eraseFromParent();
7987 auto [Dst, Src] =
MI.getFirst2Regs();
7992 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8020 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8033 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8037 MI.eraseFromParent();
8045 auto [Dst, Src] =
MI.getFirst2Regs();
8050 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8063 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8065 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8070 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8072 MI.eraseFromParent();
8080 auto [Dst, Src] =
MI.getFirst2Regs();
8084 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8095 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8096 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8098 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8105 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8106 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8107 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8109 MI.eraseFromParent();
8119 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8125 MI.eraseFromParent();
8130 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8133 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8134 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8135 MIRBuilder.buildSelect(Dst, Src, True, False);
8136 MI.eraseFromParent();
8140 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8160 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8167 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8168 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8169 MIRBuilder.buildSelect(Dst, Src, True, False);
8170 MI.eraseFromParent();
8174 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8197 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8198 MI.eraseFromParent();
8206 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8210 if (SrcTy !=
S64 && SrcTy !=
S32)
8212 if (DstTy !=
S32 && DstTy !=
S64)
8239 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8241 MI.eraseFromParent();
8246 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8251 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8258 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8260 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8261 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8263 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8264 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8266 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8268 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8269 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8270 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8273 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8274 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8275 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8277 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8280 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8285 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8286 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8292 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8294 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8295 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8297 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8302 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8303 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8305 MI.eraseFromParent();
8311 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8313 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8314 unsigned SatWidth = DstTy.getScalarSizeInBits();
8318 APInt MinInt, MaxInt;
8341 if (AreExactFloatBounds) {
8343 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8345 SrcTy.changeElementSize(1), Src, MaxC);
8346 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8348 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8358 MI.eraseFromParent();
8363 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8365 DstTy.changeElementSize(1), Src, Src);
8368 MI.eraseFromParent();
8375 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8384 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8395 MI.eraseFromParent();
8401 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8403 DstTy.changeElementSize(1), Src, Src);
8405 MI.eraseFromParent();
8415 auto [Dst, Src] =
MI.getFirst2Regs();
8417 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8419 if (MRI.getType(Src).isVector())
8423 unsigned Flags =
MI.getFlags();
8426 MI.eraseFromParent();
8430 const unsigned ExpMask = 0x7ff;
8431 const unsigned ExpBiasf64 = 1023;
8432 const unsigned ExpBiasf16 = 15;
8461 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8521 MI.eraseFromParent();
8527 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8531 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8538 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8539 LLT Ty = MRI.getType(Dst);
8541 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8542 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8543 MI.eraseFromParent();
8549 case TargetOpcode::G_SMIN:
8551 case TargetOpcode::G_SMAX:
8553 case TargetOpcode::G_UMIN:
8555 case TargetOpcode::G_UMAX:
8563 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8568 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8569 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8571 MI.eraseFromParent();
8580 LLT DstTy = MRI.getType(Dst);
8581 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8591 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8592 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8594 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8597 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8598 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8601 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8602 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8604 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8605 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8611 unsigned BoolExtOp =
8613 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8614 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8618 MI.eraseFromParent();
8624 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8625 const int Src0Size = Src0Ty.getScalarSizeInBits();
8626 const int Src1Size = Src1Ty.getScalarSizeInBits();
8631 auto NotSignBitMask =
MIRBuilder.buildConstant(
8636 if (Src0Ty == Src1Ty) {
8637 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8638 }
else if (Src0Size > Src1Size) {
8639 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8640 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8641 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8642 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8644 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8645 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8646 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8647 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8653 unsigned Flags =
MI.getFlags();
8660 MI.eraseFromParent();
8671 switch (
MI.getOpcode()) {
8672 case TargetOpcode::G_FMINNUM:
8673 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8675 case TargetOpcode::G_FMINIMUMNUM:
8676 NewOp = TargetOpcode::G_FMINNUM;
8678 case TargetOpcode::G_FMAXNUM:
8679 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8681 case TargetOpcode::G_FMAXIMUMNUM:
8682 NewOp = TargetOpcode::G_FMAXNUM;
8688 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8689 LLT Ty = MRI.getType(Dst);
8699 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8702 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8707 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8708 MI.eraseFromParent();
8715 LLT Ty = MRI.getType(DstReg);
8716 unsigned Flags =
MI.getFlags();
8721 MI.eraseFromParent();
8727 auto [DstReg,
X] =
MI.getFirst2Regs();
8728 const unsigned Flags =
MI.getFlags();
8729 const LLT Ty = MRI.getType(DstReg);
8741 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8743 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8748 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8749 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8750 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8751 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8753 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8755 MI.eraseFromParent();
8760 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8761 unsigned Flags =
MI.getFlags();
8762 LLT Ty = MRI.getType(DstReg);
8769 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8770 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8773 SrcReg, Zero, Flags);
8775 SrcReg, Trunc, Flags);
8779 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8780 MI.eraseFromParent();
8786 const unsigned NumOps =
MI.getNumOperands();
8787 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8788 unsigned PartSize = Src0Ty.getSizeInBits();
8793 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8794 const unsigned Offset = (
I - 1) * PartSize;
8797 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8800 MRI.createGenericVirtualRegister(WideTy);
8803 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8804 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8805 ResultReg = NextResult;
8808 if (DstTy.isPointer()) {
8809 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8810 DstTy.getAddressSpace())) {
8818 MI.eraseFromParent();
8824 const unsigned NumDst =
MI.getNumOperands() - 1;
8825 Register SrcReg =
MI.getOperand(NumDst).getReg();
8826 Register Dst0Reg =
MI.getOperand(0).getReg();
8827 LLT DstTy = MRI.getType(Dst0Reg);
8836 LLT IntTy = MRI.getType(SrcReg);
8841 unsigned Offset = DstSize;
8842 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
8844 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
8848 MI.eraseFromParent();
8867 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
8868 InsertVal =
MI.getOperand(2).getReg();
8870 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
8872 LLT VecTy = MRI.getType(SrcVec);
8882 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
8883 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
8885 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
8888 MI.eraseFromParent();
8893 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
8904 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
8911 int64_t
Offset = IdxVal * EltBytes;
8922 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
8925 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
8927 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
8930 MI.eraseFromParent();
8936 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
8937 MI.getFirst3RegLLTs();
8945 for (
int Idx : Mask) {
8947 if (!Undef.isValid())
8948 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
8953 if (Src0Ty.isScalar()) {
8954 BuildVec.
push_back(Idx == 0 ? Src0Reg : Src1Reg);
8956 int NumElts = Src0Ty.getNumElements();
8957 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
8958 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
8959 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
8960 auto Extract =
MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK);
8965 if (DstTy.isVector())
8966 MIRBuilder.buildBuildVector(DstReg, BuildVec);
8969 MI.eraseFromParent();
8975 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
8976 MI.getFirst4RegLLTs();
8978 if (VecTy.isScalableVector())
8994 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
8997 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9000 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9003 std::optional<APInt> PassthruSplatVal =
9006 if (PassthruSplatVal.has_value()) {
9008 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9009 }
else if (HasPassthru) {
9010 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9011 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9017 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9021 unsigned NumElmts = VecTy.getNumElements();
9022 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9024 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9027 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9030 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9035 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9037 if (HasPassthru &&
I == NumElmts - 1) {
9040 auto AllLanesSelected =
MIRBuilder.buildICmp(
9042 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9043 {OutPos, EndOfVector});
9047 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9049 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9054 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9056 MI.eraseFromParent();
9067 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9073 if (Alignment >
Align(1)) {
9076 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9085 const auto &MF = *
MI.getMF();
9091 Register AllocSize =
MI.getOperand(1).getReg();
9094 LLT PtrTy = MRI.getType(Dst);
9095 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9102 MI.eraseFromParent();
9108 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9113 MI.eraseFromParent();
9119 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9124 MI.eraseFromParent();
9130 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9131 unsigned Offset =
MI.getOperand(2).getImm();
9134 if (SrcTy.isVector()) {
9135 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9136 unsigned DstSize = DstTy.getSizeInBits();
9138 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9139 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9141 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9145 for (
unsigned Idx =
Offset / SrcEltSize;
9146 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9147 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9149 if (SubVectorElts.
size() == 1)
9150 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9152 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9154 MI.eraseFromParent();
9159 if (DstTy.isScalar() &&
9160 (SrcTy.isScalar() ||
9161 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9162 LLT SrcIntTy = SrcTy;
9163 if (!SrcTy.isScalar()) {
9165 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9172 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9176 MI.eraseFromParent();
9184 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9187 LLT DstTy = MRI.getType(Src);
9188 LLT InsertTy = MRI.getType(InsertSrc);
9196 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9198 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9202 for (; Idx <
Offset / EltSize; ++Idx) {
9203 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9208 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9209 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9211 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9220 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9223 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9224 MI.eraseFromParent();
9238 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9242 LLT IntDstTy = DstTy;
9246 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9251 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9257 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9263 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9264 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9265 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9268 MI.eraseFromParent();
9274 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9275 MI.getFirst4RegLLTs();
9276 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9279 LLT BoolTy = Dst1Ty;
9281 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9298 auto ResultLowerThanLHS =
9303 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9306 MI.eraseFromParent();
9312 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9313 const LLT Ty = MRI.getType(Res);
9316 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9317 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9318 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9329 MI.eraseFromParent();
9335 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9336 LLT Ty = MRI.getType(Res);
9340 switch (
MI.getOpcode()) {
9343 case TargetOpcode::G_UADDSAT:
9346 BaseOp = TargetOpcode::G_ADD;
9348 case TargetOpcode::G_SADDSAT:
9351 BaseOp = TargetOpcode::G_ADD;
9353 case TargetOpcode::G_USUBSAT:
9356 BaseOp = TargetOpcode::G_SUB;
9358 case TargetOpcode::G_SSUBSAT:
9361 BaseOp = TargetOpcode::G_SUB;
9376 uint64_t NumBits = Ty.getScalarSizeInBits();
9387 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9395 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9400 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9401 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9404 MI.eraseFromParent();
9410 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9411 LLT Ty = MRI.getType(Res);
9415 unsigned OverflowOp;
9416 switch (
MI.getOpcode()) {
9419 case TargetOpcode::G_UADDSAT:
9422 OverflowOp = TargetOpcode::G_UADDO;
9424 case TargetOpcode::G_SADDSAT:
9427 OverflowOp = TargetOpcode::G_SADDO;
9429 case TargetOpcode::G_USUBSAT:
9432 OverflowOp = TargetOpcode::G_USUBO;
9434 case TargetOpcode::G_SSUBSAT:
9437 OverflowOp = TargetOpcode::G_SSUBO;
9442 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9443 Register Tmp = OverflowRes.getReg(0);
9444 Register Ov = OverflowRes.getReg(1);
9453 uint64_t NumBits = Ty.getScalarSizeInBits();
9454 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9455 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9458 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9466 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9470 MI.eraseFromParent();
9476 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9477 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9478 "Expected shlsat opcode!");
9479 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9480 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9481 LLT Ty = MRI.getType(Res);
9485 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9486 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9495 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9500 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9502 MI.eraseFromParent();
9507 auto [Dst, Src] =
MI.getFirst2Regs();
9508 const LLT Ty = MRI.getType(Src);
9509 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9510 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9513 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9514 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9515 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9516 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9519 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9521 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9522 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9523 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9525 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9526 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9527 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9529 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9530 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9531 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9533 Res.getInstr()->getOperand(0).setReg(Dst);
9535 MI.eraseFromParent();
9542 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9545 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9546 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9547 return B.buildOr(Dst,
LHS,
RHS);
9552 auto [Dst, Src] =
MI.getFirst2Regs();
9553 const LLT SrcTy = MRI.getType(Src);
9554 unsigned Size = SrcTy.getScalarSizeInBits();
9555 unsigned VSize = SrcTy.getSizeInBits();
9558 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9559 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9560 {LLT::fixed_vector(VSize / 8, 8),
9561 LLT::fixed_vector(VSize / 8, 8)}}))) {
9566 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9567 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9568 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9572 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9595 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9599 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9602 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9606 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9610 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9615 MI.eraseFromParent();
9623 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9624 int NameOpIdx = IsRead ? 1 : 0;
9625 int ValRegIndex = IsRead ? 0 : 1;
9627 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9628 const LLT Ty = MRI.getType(ValReg);
9630 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9637 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9638 Fn,
MI.getDebugLoc()));
9642 MI.eraseFromParent();
9651 MI.eraseFromParent();
9657 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9658 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9660 LLT OrigTy = MRI.getType(Result);
9664 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9665 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9667 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9669 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9670 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9673 MI.eraseFromParent();
9679 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9684 MI.eraseFromParent();
9689 MI.eraseFromParent();
9696 unsigned BitSize = SrcTy.getScalarSizeInBits();
9700 if (SrcTy.isVector())
9701 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9702 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9708 APInt ExpMask = Inf;
9714 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9715 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9716 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9717 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9718 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9720 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9724 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9726 LLT DstTyCopy = DstTy;
9728 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9756 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9759 Mask &= ~PartialCheck;
9768 else if (PartialCheck ==
fcZero)
9780 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9781 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9784 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9786 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9787 appendToRes(SubnormalRes);
9794 else if (PartialCheck ==
fcInf)
9799 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9806 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
9807 if (PartialCheck ==
fcNan) {
9811 }
else if (PartialCheck ==
fcQNan) {
9821 Abs, InfWithQnanBitC);
9822 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
9829 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
9831 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
9832 APInt MaxExpMinusOne = ExpMask - ExpLSB;
9835 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
9837 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
9840 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
9841 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
9843 appendToRes(NormalRes);
9847 MI.eraseFromParent();
9853 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
9854 MI.getFirst4RegLLTs();
9856 bool IsEltPtr = DstTy.isPointerOrPointerVector();
9860 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
9861 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
9865 if (MaskTy.isScalar()) {
9873 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
9877 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
9879 if (DstTy.isVector()) {
9881 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
9882 MaskReg = ShufSplat.getReg(0);
9887 }
else if (!DstTy.isVector()) {
9892 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
9896 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
9897 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
9898 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
9905 MI.eraseFromParent();
9911 unsigned Opcode =
MI.getOpcode();
9914 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
9915 : TargetOpcode::G_UDIV,
9916 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9918 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
9919 : TargetOpcode::G_UREM,
9920 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9921 MI.eraseFromParent();
9931 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
9935 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
9938 MI.eraseFromParent();
9949 LLT Ty = MRI.getType(SrcReg);
9953 MI.eraseFromParent();
9960 Register DestReg =
MI.getOperand(0).getReg();
9962 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
9966 MI.eraseFromParent();
9972 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
9973 MI.getOpcode() == TargetOpcode::G_ABDU) &&
9974 "Expected G_ABDS or G_ABDU instruction");
9976 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
9977 LLT Ty = MRI.getType(LHS);
9987 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
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);
10005 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10006 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10007 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10009 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10010 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10012 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10014 MI.eraseFromParent();
10019 Register SrcReg =
MI.getOperand(1).getReg();
10020 Register DstReg =
MI.getOperand(0).getReg();
10022 LLT Ty = MRI.getType(DstReg);
10030 MI.eraseFromParent();
10036 Register SrcReg =
MI.getOperand(1).getReg();
10037 LLT SrcTy = MRI.getType(SrcReg);
10038 LLT DstTy = MRI.getType(SrcReg);
10041 if (SrcTy.isScalar()) {
10046 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10057 Register ListPtr =
MI.getOperand(1).getReg();
10058 LLT PtrTy = MRI.getType(ListPtr);
10065 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10067 const Align A(
MI.getOperand(2).getImm());
10069 if (
A > TLI.getMinStackArgumentAlignment()) {
10071 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10072 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10073 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10074 VAList = AndDst.getReg(0);
10081 LLT LLTTy = MRI.getType(Dst);
10084 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10085 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10090 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10092 Align EltAlignment =
DL.getABITypeAlign(Ty);
10095 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10097 MI.eraseFromParent();
10112 unsigned Limit,
const MemOp &
Op,
10113 unsigned DstAS,
unsigned SrcAS,
10114 const AttributeList &FuncAttributes,
10116 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10126 if (
Op.isFixedDstAlign())
10127 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10130 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10134 unsigned NumMemOps = 0;
10137 unsigned TySize = Ty.getSizeInBytes();
10138 while (TySize >
Size) {
10147 assert(NewTySize > 0 &&
"Could not find appropriate type");
10154 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10156 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10162 TySize = NewTySize;
10166 if (++NumMemOps > Limit)
10169 MemOps.push_back(Ty);
10179 unsigned NumBits = Ty.getScalarSizeInBits();
10181 if (!Ty.isVector() && ValVRegAndVal) {
10182 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10190 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10211 uint64_t KnownLen,
Align Alignment,
10213 auto &MF = *
MI.getParent()->getParent();
10218 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10220 bool DstAlignCanChange =
false;
10224 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10226 DstAlignCanChange =
true;
10228 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10229 std::vector<LLT> MemOps;
10231 const auto &DstMMO = **
MI.memoperands_begin();
10232 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10235 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10246 if (DstAlignCanChange) {
10249 Align NewAlign =
DL.getABITypeAlign(IRTy);
10250 if (NewAlign > Alignment) {
10251 Alignment = NewAlign;
10259 MachineIRBuilder MIB(
MI);
10261 LLT LargestTy = MemOps[0];
10262 for (
unsigned i = 1; i < MemOps.size(); i++)
10264 LargestTy = MemOps[i];
10276 LLT PtrTy = MRI.getType(Dst);
10277 unsigned DstOff = 0;
10278 unsigned Size = KnownLen;
10279 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10280 LLT Ty = MemOps[
I];
10282 if (TySize >
Size) {
10285 assert(
I == MemOps.size() - 1 &&
I != 0);
10286 DstOff -= TySize -
Size;
10296 TLI.isTruncateFree(LargestVT, VT))
10297 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10310 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10313 MIB.buildStore(
Value,
Ptr, *StoreMMO);
10318 MI.eraseFromParent();
10324 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10326 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10328 const auto *MMOIt =
MI.memoperands_begin();
10330 bool IsVolatile =
MemOp->isVolatile();
10336 "inline memcpy with dynamic size is not yet supported");
10337 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10338 if (KnownLen == 0) {
10339 MI.eraseFromParent();
10343 const auto &DstMMO = **
MI.memoperands_begin();
10344 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10345 Align DstAlign = DstMMO.getBaseAlign();
10346 Align SrcAlign = SrcMMO.getBaseAlign();
10348 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10355 Align SrcAlign,
bool IsVolatile) {
10356 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10357 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10358 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10365 Align SrcAlign,
bool IsVolatile) {
10366 auto &MF = *
MI.getParent()->getParent();
10371 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10373 bool DstAlignCanChange =
false;
10375 Align Alignment = std::min(DstAlign, SrcAlign);
10379 DstAlignCanChange =
true;
10385 std::vector<LLT> MemOps;
10387 const auto &DstMMO = **
MI.memoperands_begin();
10388 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10394 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10400 if (DstAlignCanChange) {
10403 Align NewAlign =
DL.getABITypeAlign(IRTy);
10408 if (!
TRI->hasStackRealignment(MF))
10410 NewAlign = std::min(NewAlign, *StackAlign);
10412 if (NewAlign > Alignment) {
10413 Alignment = NewAlign;
10421 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10423 MachineIRBuilder MIB(
MI);
10429 unsigned CurrOffset = 0;
10430 unsigned Size = KnownLen;
10431 for (
auto CopyTy : MemOps) {
10434 if (CopyTy.getSizeInBytes() >
Size)
10435 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10446 if (CurrOffset != 0) {
10447 LLT SrcTy = MRI.getType(Src);
10450 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10452 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10456 if (CurrOffset != 0) {
10457 LLT DstTy = MRI.getType(Dst);
10458 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10460 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10461 CurrOffset += CopyTy.getSizeInBytes();
10462 Size -= CopyTy.getSizeInBytes();
10465 MI.eraseFromParent();
10471 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10473 auto &MF = *
MI.getParent()->getParent();
10478 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10480 bool DstAlignCanChange =
false;
10483 Align Alignment = std::min(DstAlign, SrcAlign);
10485 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10487 DstAlignCanChange =
true;
10489 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10490 std::vector<LLT> MemOps;
10492 const auto &DstMMO = **
MI.memoperands_begin();
10493 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10494 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10495 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10502 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10508 if (DstAlignCanChange) {
10511 Align NewAlign =
DL.getABITypeAlign(IRTy);
10516 if (!
TRI->hasStackRealignment(MF))
10517 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10518 NewAlign = std::min(NewAlign, *StackAlign);
10520 if (NewAlign > Alignment) {
10521 Alignment = NewAlign;
10529 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10531 MachineIRBuilder MIB(
MI);
10535 unsigned CurrOffset = 0;
10536 SmallVector<Register, 16> LoadVals;
10537 for (
auto CopyTy : MemOps) {
10544 if (CurrOffset != 0) {
10545 LLT SrcTy = MRI.getType(Src);
10548 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10550 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10551 CurrOffset += CopyTy.getSizeInBytes();
10555 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10556 LLT CopyTy = MemOps[
I];
10562 if (CurrOffset != 0) {
10563 LLT DstTy = MRI.getType(Dst);
10566 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10568 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10571 MI.eraseFromParent();
10577 const unsigned Opc =
MI.getOpcode();
10580 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10581 Opc == TargetOpcode::G_MEMSET) &&
10582 "Expected memcpy like instruction");
10584 auto MMOIt =
MI.memoperands_begin();
10589 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10591 if (
Opc != TargetOpcode::G_MEMSET) {
10592 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10593 MemOp = *(++MMOIt);
10594 SrcAlign =
MemOp->getBaseAlign();
10599 if (!LenVRegAndVal)
10601 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10603 if (KnownLen == 0) {
10604 MI.eraseFromParent();
10608 if (MaxLen && KnownLen > MaxLen)
10611 bool IsVolatile =
MemOp->isVolatile();
10612 if (
Opc == TargetOpcode::G_MEMCPY) {
10613 auto &MF = *
MI.getParent()->getParent();
10616 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10617 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10620 if (
Opc == TargetOpcode::G_MEMMOVE)
10621 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10622 if (
Opc == TargetOpcode::G_MEMSET)
10623 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 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)