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:
2943 case TargetOpcode::G_ASHR:
2944 case TargetOpcode::G_LSHR:
2948 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
2949 : TargetOpcode::G_ZEXT;
2962 case TargetOpcode::G_UDIV:
2963 case TargetOpcode::G_UREM:
2964 case TargetOpcode::G_ABDU:
2971 case TargetOpcode::G_UDIVREM:
2980 case TargetOpcode::G_UMIN:
2981 case TargetOpcode::G_UMAX: {
2982 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
2984 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
2988 ? TargetOpcode::G_SEXT
2989 : TargetOpcode::G_ZEXT;
2999 case TargetOpcode::G_SELECT:
3009 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3016 case TargetOpcode::G_FPTOSI:
3017 case TargetOpcode::G_FPTOUI:
3018 case TargetOpcode::G_INTRINSIC_LRINT:
3019 case TargetOpcode::G_INTRINSIC_LLRINT:
3020 case TargetOpcode::G_IS_FPCLASS:
3030 case TargetOpcode::G_SITOFP:
3040 case TargetOpcode::G_UITOFP:
3050 case TargetOpcode::G_FPTOSI_SAT:
3051 case TargetOpcode::G_FPTOUI_SAT:
3056 LLT Ty = MRI.getType(OldDst);
3057 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3059 MI.getOperand(0).setReg(ExtReg);
3060 uint64_t ShortBits = Ty.getScalarSizeInBits();
3063 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3074 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3075 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3083 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3091 case TargetOpcode::G_LOAD:
3092 case TargetOpcode::G_SEXTLOAD:
3093 case TargetOpcode::G_ZEXTLOAD:
3099 case TargetOpcode::G_STORE: {
3103 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3104 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3105 if (!Ty.isScalar()) {
3113 MI.setMemRefs(MF, {NewMMO});
3120 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3121 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3127 case TargetOpcode::G_CONSTANT: {
3130 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3131 MRI.getType(
MI.getOperand(0).getReg()));
3132 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3133 ExtOpc == TargetOpcode::G_ANYEXT) &&
3136 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3140 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3146 case TargetOpcode::G_FCONSTANT: {
3152 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3154 MI.eraseFromParent();
3157 case TargetOpcode::G_IMPLICIT_DEF: {
3163 case TargetOpcode::G_BRCOND:
3169 case TargetOpcode::G_FCMP:
3180 case TargetOpcode::G_ICMP:
3185 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3189 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3190 unsigned ExtOpcode =
3194 ? TargetOpcode::G_SEXT
3195 : TargetOpcode::G_ZEXT;
3202 case TargetOpcode::G_PTR_ADD:
3203 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3209 case TargetOpcode::G_PHI: {
3210 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3213 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3225 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3228 LLT VecTy = MRI.getType(VecReg);
3233 TargetOpcode::G_ANYEXT);
3248 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3264 LLT VecTy = MRI.getType(VecReg);
3284 case TargetOpcode::G_FADD:
3285 case TargetOpcode::G_FMUL:
3286 case TargetOpcode::G_FSUB:
3287 case TargetOpcode::G_FMA:
3288 case TargetOpcode::G_FMAD:
3289 case TargetOpcode::G_FNEG:
3290 case TargetOpcode::G_FABS:
3291 case TargetOpcode::G_FCANONICALIZE:
3292 case TargetOpcode::G_FMINNUM:
3293 case TargetOpcode::G_FMAXNUM:
3294 case TargetOpcode::G_FMINNUM_IEEE:
3295 case TargetOpcode::G_FMAXNUM_IEEE:
3296 case TargetOpcode::G_FMINIMUM:
3297 case TargetOpcode::G_FMAXIMUM:
3298 case TargetOpcode::G_FMINIMUMNUM:
3299 case TargetOpcode::G_FMAXIMUMNUM:
3300 case TargetOpcode::G_FDIV:
3301 case TargetOpcode::G_FREM:
3302 case TargetOpcode::G_FCEIL:
3303 case TargetOpcode::G_FFLOOR:
3304 case TargetOpcode::G_FCOS:
3305 case TargetOpcode::G_FSIN:
3306 case TargetOpcode::G_FTAN:
3307 case TargetOpcode::G_FACOS:
3308 case TargetOpcode::G_FASIN:
3309 case TargetOpcode::G_FATAN:
3310 case TargetOpcode::G_FATAN2:
3311 case TargetOpcode::G_FCOSH:
3312 case TargetOpcode::G_FSINH:
3313 case TargetOpcode::G_FTANH:
3314 case TargetOpcode::G_FLOG10:
3315 case TargetOpcode::G_FLOG:
3316 case TargetOpcode::G_FLOG2:
3317 case TargetOpcode::G_FRINT:
3318 case TargetOpcode::G_FNEARBYINT:
3319 case TargetOpcode::G_FSQRT:
3320 case TargetOpcode::G_FEXP:
3321 case TargetOpcode::G_FEXP2:
3322 case TargetOpcode::G_FEXP10:
3323 case TargetOpcode::G_FPOW:
3324 case TargetOpcode::G_INTRINSIC_TRUNC:
3325 case TargetOpcode::G_INTRINSIC_ROUND:
3326 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3330 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3336 case TargetOpcode::G_FPOWI:
3337 case TargetOpcode::G_FLDEXP:
3338 case TargetOpcode::G_STRICT_FLDEXP: {
3340 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3361 case TargetOpcode::G_FFREXP: {
3374 case TargetOpcode::G_INTTOPTR:
3382 case TargetOpcode::G_PTRTOINT:
3390 case TargetOpcode::G_BUILD_VECTOR: {
3394 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3400 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3408 case TargetOpcode::G_SEXT_INREG:
3417 case TargetOpcode::G_PTRMASK: {
3425 case TargetOpcode::G_VECREDUCE_ADD: {
3434 case TargetOpcode::G_VECREDUCE_FADD:
3435 case TargetOpcode::G_VECREDUCE_FMUL:
3436 case TargetOpcode::G_VECREDUCE_FMIN:
3437 case TargetOpcode::G_VECREDUCE_FMAX:
3438 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3439 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3444 LLT VecTy = MRI.getType(VecReg);
3453 case TargetOpcode::G_VSCALE: {
3460 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3465 case TargetOpcode::G_SPLAT_VECTOR: {
3474 case TargetOpcode::G_INSERT_SUBVECTOR: {
3482 LLT SubVecTy = MRI.getType(SubVec);
3486 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3487 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3488 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3492 auto SplatZero =
MIRBuilder.buildSplatVector(
3497 MI.eraseFromParent();
3506 auto Unmerge =
B.buildUnmerge(Ty, Src);
3507 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3516 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3518 LLT DstLLT =
MRI.getType(DstReg);
3530 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3539 MI.eraseFromParent();
3550 MI.eraseFromParent();
3557 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3558 if (SrcTy.isVector()) {
3562 if (DstTy.isVector()) {
3563 int NumDstElt = DstTy.getNumElements();
3564 int NumSrcElt = SrcTy.getNumElements();
3567 LLT DstCastTy = DstEltTy;
3568 LLT SrcPartTy = SrcEltTy;
3572 if (NumSrcElt < NumDstElt) {
3582 SrcPartTy = SrcEltTy;
3583 }
else if (NumSrcElt > NumDstElt) {
3594 DstCastTy = DstEltTy;
3599 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3603 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3604 MI.eraseFromParent();
3608 if (DstTy.isVector()) {
3611 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3612 MI.eraseFromParent();
3628 unsigned NewEltSize,
3629 unsigned OldEltSize) {
3630 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3631 LLT IdxTy =
B.getMRI()->getType(Idx);
3634 auto OffsetMask =
B.buildConstant(
3636 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3637 return B.buildShl(IdxTy, OffsetIdx,
3638 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3653 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3657 unsigned OldNumElts = SrcVecTy.getNumElements();
3664 if (NewNumElts > OldNumElts) {
3675 if (NewNumElts % OldNumElts != 0)
3679 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3683 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3686 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3688 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3689 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3690 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3691 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3692 NewOps[
I] = Elt.getReg(0);
3695 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3697 MI.eraseFromParent();
3701 if (NewNumElts < OldNumElts) {
3702 if (NewEltSize % OldEltSize != 0)
3724 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3725 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3728 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3732 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3733 ScaledIdx).getReg(0);
3741 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3743 MI.eraseFromParent();
3757 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3758 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3759 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3760 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3763 auto EltMask =
B.buildConstant(
3767 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3768 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3771 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3775 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3789 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3790 MI.getFirst4RegLLTs();
3802 if (NewNumElts < OldNumElts) {
3803 if (NewEltSize % OldEltSize != 0)
3812 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3813 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3816 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3820 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3821 ScaledIdx).getReg(0);
3831 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3832 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3836 MI.eraseFromParent();
3866 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3870 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3871 return UnableToLegalize;
3876 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3878 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3887 MI.eraseFromParent();
3905 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3906 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3916 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3917 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3919 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
3920 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
3922 MI.eraseFromParent();
3952 LLT DstTy = MRI.getType(Dst);
3953 LLT SrcTy = MRI.getType(Src);
3959 if (DstTy == CastTy)
3967 if (CastEltSize < DstEltSize)
3970 auto AdjustAmt = CastEltSize / DstEltSize;
3971 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
3972 SrcTyMinElts % AdjustAmt != 0)
3977 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
3978 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
3981 ES->eraseFromParent();
4016 LLT DstTy = MRI.getType(Dst);
4017 LLT BigVecTy = MRI.getType(BigVec);
4018 LLT SubVecTy = MRI.getType(SubVec);
4020 if (DstTy == CastTy)
4035 if (CastEltSize < DstEltSize)
4038 auto AdjustAmt = CastEltSize / DstEltSize;
4039 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4040 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4046 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4047 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4049 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4052 ES->eraseFromParent();
4060 LLT DstTy = MRI.getType(DstReg);
4068 if (MemSizeInBits != MemStoreSizeInBits) {
4085 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4089 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4090 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4092 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4095 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4097 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4100 if (DstTy != LoadTy)
4108 if (
MIRBuilder.getDataLayout().isBigEndian())
4126 uint64_t LargeSplitSize, SmallSplitSize;
4131 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4138 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4141 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4152 if (Alignment.
value() * 8 > MemSizeInBits &&
4157 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4174 LLT PtrTy = MRI.getType(PtrReg);
4177 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4181 LargeSplitSize / 8);
4182 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4183 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4185 SmallPtr, *SmallMMO);
4187 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4188 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4190 if (AnyExtTy == DstTy)
4191 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4193 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4197 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4217 LLT SrcTy = MRI.getType(SrcReg);
4225 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4231 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4233 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4237 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4241 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4256 uint64_t LargeSplitSize, SmallSplitSize;
4263 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4266 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4275 if (SrcTy.isPointer()) {
4277 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4280 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4283 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4284 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4287 LLT PtrTy = MRI.getType(PtrReg);
4290 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4296 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4297 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4306 LLT SrcTy = MRI.getType(SrcReg);
4312 assert(SrcTy.isVector() &&
"Expect a vector store type");
4319 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4323 auto Elt =
MIRBuilder.buildExtractVectorElement(
4324 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4325 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4326 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4332 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4333 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4337 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4348 switch (
MI.getOpcode()) {
4349 case TargetOpcode::G_LOAD: {
4367 case TargetOpcode::G_STORE: {
4383 case TargetOpcode::G_SELECT: {
4387 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4389 dbgs() <<
"bitcast action not implemented for vector select\n");
4400 case TargetOpcode::G_AND:
4401 case TargetOpcode::G_OR:
4402 case TargetOpcode::G_XOR: {
4410 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4412 case TargetOpcode::G_INSERT_VECTOR_ELT:
4414 case TargetOpcode::G_CONCAT_VECTORS:
4416 case TargetOpcode::G_SHUFFLE_VECTOR:
4418 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4420 case TargetOpcode::G_INSERT_SUBVECTOR:
4428void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4438 switch(
MI.getOpcode()) {
4441 case TargetOpcode::G_FCONSTANT:
4443 case TargetOpcode::G_BITCAST:
4445 case TargetOpcode::G_SREM:
4446 case TargetOpcode::G_UREM: {
4447 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4449 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4450 {MI.getOperand(1), MI.getOperand(2)});
4452 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4454 MI.eraseFromParent();
4457 case TargetOpcode::G_SADDO:
4458 case TargetOpcode::G_SSUBO:
4460 case TargetOpcode::G_SADDE:
4462 case TargetOpcode::G_SSUBE:
4464 case TargetOpcode::G_UMULH:
4465 case TargetOpcode::G_SMULH:
4467 case TargetOpcode::G_SMULO:
4468 case TargetOpcode::G_UMULO: {
4471 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4472 LLT Ty = MRI.getType(Res);
4474 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4475 ? TargetOpcode::G_SMULH
4476 : TargetOpcode::G_UMULH;
4480 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4481 MI.removeOperand(1);
4484 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4492 if (Opcode == TargetOpcode::G_SMULH) {
4493 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4494 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4501 case TargetOpcode::G_FNEG: {
4502 auto [Res, SubByReg] =
MI.getFirst2Regs();
4503 LLT Ty = MRI.getType(Res);
4507 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4508 MI.eraseFromParent();
4511 case TargetOpcode::G_FSUB:
4512 case TargetOpcode::G_STRICT_FSUB: {
4513 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4514 LLT Ty = MRI.getType(Res);
4519 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4520 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4524 MI.eraseFromParent();
4527 case TargetOpcode::G_FMAD:
4529 case TargetOpcode::G_FFLOOR:
4531 case TargetOpcode::G_LROUND:
4532 case TargetOpcode::G_LLROUND: {
4535 LLT SrcTy = MRI.getType(SrcReg);
4536 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4539 MI.eraseFromParent();
4542 case TargetOpcode::G_INTRINSIC_ROUND:
4544 case TargetOpcode::G_FRINT: {
4547 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4550 case TargetOpcode::G_INTRINSIC_LRINT:
4551 case TargetOpcode::G_INTRINSIC_LLRINT: {
4554 LLT SrcTy = MRI.getType(SrcReg);
4556 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4558 MI.eraseFromParent();
4561 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4562 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4563 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4564 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4565 **
MI.memoperands_begin());
4567 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4568 MI.eraseFromParent();
4571 case TargetOpcode::G_LOAD:
4572 case TargetOpcode::G_SEXTLOAD:
4573 case TargetOpcode::G_ZEXTLOAD:
4575 case TargetOpcode::G_STORE:
4577 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4578 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4579 case TargetOpcode::G_CTLZ:
4580 case TargetOpcode::G_CTTZ:
4581 case TargetOpcode::G_CTPOP:
4584 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4586 Register NewRes = MRI.cloneVirtualRegister(Res);
4593 MI.eraseFromParent();
4597 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4598 const LLT CondTy = MRI.getType(CarryOut);
4599 const LLT Ty = MRI.getType(Res);
4601 Register NewRes = MRI.cloneVirtualRegister(Res);
4604 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4610 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4611 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4618 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4623 MI.eraseFromParent();
4627 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4632 MI.eraseFromParent();
4636 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4637 const LLT CondTy = MRI.getType(BorrowOut);
4638 const LLT Ty = MRI.getType(Res);
4641 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4647 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4648 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4655 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4656 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4658 MI.eraseFromParent();
4691 case G_MERGE_VALUES:
4693 case G_UNMERGE_VALUES:
4695 case TargetOpcode::G_SEXT_INREG: {
4696 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4697 int64_t SizeInBits =
MI.getOperand(2).getImm();
4699 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4700 LLT DstTy = MRI.getType(DstReg);
4701 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4704 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4705 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4706 MI.eraseFromParent();
4709 case G_EXTRACT_VECTOR_ELT:
4710 case G_INSERT_VECTOR_ELT:
4712 case G_SHUFFLE_VECTOR:
4714 case G_VECTOR_COMPRESS:
4716 case G_DYN_STACKALLOC:
4720 case G_STACKRESTORE:
4730 case G_READ_REGISTER:
4731 case G_WRITE_REGISTER:
4738 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4739 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4745 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4750 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4761 bool IsSigned =
MI.getOpcode() == G_ABDS;
4762 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4763 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4764 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4788 case G_MEMCPY_INLINE:
4789 return lowerMemcpyInline(
MI);
4800 case G_ATOMICRMW_SUB: {
4801 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4802 const LLT ValTy = MRI.getType(Val);
4806 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4807 MI.eraseFromParent();
4830 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4834 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4840 Align StackTypeAlign =
4847 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4848 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4853 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4865 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4868 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4879 "Converting bits to bytes lost precision");
4885 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4886 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4888 if (IdxTy != MRI.getType(Index))
4889 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4894 LLT PtrTy = MRI.getType(VecPtr);
4895 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4903 std::initializer_list<unsigned> NonVecOpIndices) {
4904 if (
MI.getNumMemOperands() != 0)
4907 LLT VecTy =
MRI.getType(
MI.getReg(0));
4921 if (!Ty.isVector()) {
4927 if (Ty.getNumElements() != NumElts)
4942 assert(Ty.isVector() &&
"Expected vector type");
4945 int NumParts, NumLeftover;
4946 std::tie(NumParts, NumLeftover) =
4949 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
4950 for (
int i = 0; i < NumParts; ++i) {
4955 assert(NumLeftover == 1 &&
"expected exactly one leftover");
4964 for (
unsigned i = 0; i <
N; ++i) {
4966 Ops.push_back(
Op.getReg());
4967 else if (
Op.isImm())
4968 Ops.push_back(
Op.getImm());
4969 else if (
Op.isPredicate())
4991 std::initializer_list<unsigned> NonVecOpIndices) {
4993 "Non-compatible opcode or not specified non-vector operands");
4994 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
4996 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
4997 unsigned NumDefs =
MI.getNumDefs();
5005 for (
unsigned i = 0; i < NumDefs; ++i) {
5006 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5014 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5015 ++UseIdx, ++UseNo) {
5018 MI.getOperand(UseIdx));
5027 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5031 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5033 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5034 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5037 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5038 Uses.push_back(InputOpsPieces[InputNo][i]);
5041 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5042 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5047 for (
unsigned i = 0; i < NumDefs; ++i)
5048 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5050 for (
unsigned i = 0; i < NumDefs; ++i)
5051 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5054 MI.eraseFromParent();
5061 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5063 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5064 unsigned NumDefs =
MI.getNumDefs();
5068 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5073 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5074 UseIdx += 2, ++UseNo) {
5082 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5084 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5085 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5087 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5090 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5091 Phi.addUse(InputOpsPieces[j][i]);
5092 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5102 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5104 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5107 MI.eraseFromParent();
5115 const int NumDst =
MI.getNumOperands() - 1;
5116 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5117 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5118 LLT SrcTy = MRI.getType(SrcReg);
5120 if (TypeIdx != 1 || NarrowTy == DstTy)
5127 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5130 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5144 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5145 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5146 const int PartsPerUnmerge = NumDst / NumUnmerge;
5148 for (
int I = 0;
I != NumUnmerge; ++
I) {
5149 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5151 for (
int J = 0; J != PartsPerUnmerge; ++J)
5152 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5153 MIB.addUse(Unmerge.getReg(
I));
5156 MI.eraseFromParent();
5163 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5167 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5169 if (NarrowTy == SrcTy)
5177 assert(SrcTy.isVector() &&
"Expected vector types");
5179 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5193 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5194 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5195 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5201 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5202 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5203 ++i,
Offset += NumNarrowTyElts) {
5206 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5209 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5210 MI.eraseFromParent();
5214 assert(TypeIdx == 0 &&
"Bad type index");
5215 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5230 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5231 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5233 for (
unsigned i = 0; i < NumParts; ++i) {
5235 for (
unsigned j = 0; j < NumElts; ++j)
5236 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5238 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5241 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5242 MI.eraseFromParent();
5250 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5252 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5254 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5256 InsertVal =
MI.getOperand(2).getReg();
5258 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5259 LLT VecTy = MRI.getType(SrcVec);
5265 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5269 MI.eraseFromParent();
5278 SplitPieces[IdxVal] = InsertVal;
5279 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5281 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5285 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5288 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5289 TargetOpcode::G_ANYEXT);
5293 LLT IdxTy = MRI.getType(Idx);
5294 int64_t PartIdx = IdxVal / NewNumElts;
5296 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5299 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5302 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5303 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5304 VecParts[PartIdx] = InsertPart.getReg(0);
5308 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5310 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5314 MI.eraseFromParent();
5334 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5346 LLT ValTy = MRI.getType(ValReg);
5355 int NumLeftover = -1;
5361 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5363 NumParts = NarrowRegs.
size();
5364 NumLeftover = NarrowLeftoverRegs.
size();
5371 LLT PtrTy = MRI.getType(AddrReg);
5374 unsigned TotalSize = ValTy.getSizeInBits();
5381 auto MMO = LdStMI.
getMMO();
5383 unsigned NumParts,
unsigned Offset) ->
unsigned {
5386 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5388 unsigned ByteOffset =
Offset / 8;
5391 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5398 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5399 ValRegs.push_back(Dst);
5400 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5402 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5411 unsigned HandledOffset =
5412 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5416 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5419 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5420 LeftoverTy, NarrowLeftoverRegs);
5434 switch (
MI.getOpcode()) {
5435 case G_IMPLICIT_DEF:
5451 case G_FCANONICALIZE:
5468 case G_INTRINSIC_LRINT:
5469 case G_INTRINSIC_LLRINT:
5470 case G_INTRINSIC_ROUND:
5471 case G_INTRINSIC_ROUNDEVEN:
5474 case G_INTRINSIC_TRUNC:
5501 case G_FMINNUM_IEEE:
5502 case G_FMAXNUM_IEEE:
5524 case G_CTLZ_ZERO_UNDEF:
5526 case G_CTTZ_ZERO_UNDEF:
5542 case G_ADDRSPACE_CAST:
5555 case G_STRICT_FLDEXP:
5564 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5569 case G_UNMERGE_VALUES:
5571 case G_BUILD_VECTOR:
5572 assert(TypeIdx == 0 &&
"not a vector type index");
5574 case G_CONCAT_VECTORS:
5578 case G_EXTRACT_VECTOR_ELT:
5579 case G_INSERT_VECTOR_ELT:
5588 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5589 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5591 case G_SHUFFLE_VECTOR:
5597 case G_INTRINSIC_FPTRUNC_ROUND:
5607 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5608 "Not a bitcast operation");
5613 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5615 unsigned NewElemCount =
5618 if (NewElemCount == 1) {
5621 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5627 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5636 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5637 MI.eraseFromParent();
5643 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5647 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5648 MI.getFirst3RegLLTs();
5651 if (DstTy != Src1Ty)
5653 if (DstTy != Src2Ty)
5668 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5684 unsigned InputUsed[2] = {-1U, -1U};
5685 unsigned FirstMaskIdx =
High * NewElts;
5686 bool UseBuildVector =
false;
5687 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5689 int Idx = Mask[FirstMaskIdx + MaskOffset];
5694 if (
Input >= std::size(Inputs)) {
5701 Idx -=
Input * NewElts;
5705 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5706 if (InputUsed[OpNo] ==
Input) {
5709 }
else if (InputUsed[OpNo] == -1U) {
5711 InputUsed[OpNo] =
Input;
5716 if (OpNo >= std::size(InputUsed)) {
5719 UseBuildVector =
true;
5724 Ops.push_back(Idx + OpNo * NewElts);
5727 if (UseBuildVector) {
5732 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5734 int Idx = Mask[FirstMaskIdx + MaskOffset];
5739 if (
Input >= std::size(Inputs)) {
5746 Idx -=
Input * NewElts;
5750 .buildExtractVectorElement(
5751 EltTy, Inputs[
Input],
5757 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5758 }
else if (InputUsed[0] == -1U) {
5760 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5762 Register Op0 = Inputs[InputUsed[0]];
5766 : Inputs[InputUsed[1]];
5768 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5775 MI.eraseFromParent();
5788 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5794 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5797 const unsigned NumParts =
5799 : SrcTy.getNumElements();
5803 if (DstTy != NarrowTy)
5809 unsigned NumPartsLeft = NumParts;
5810 while (NumPartsLeft > 1) {
5811 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5814 .buildInstr(ScalarOpc, {NarrowTy},
5815 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5818 SplitSrcs = PartialResults;
5819 PartialResults.
clear();
5820 NumPartsLeft = SplitSrcs.
size();
5824 MI.eraseFromParent();
5829 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5830 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5833 MI.eraseFromParent();
5837 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5839 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5847 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5850 Register Acc = PartialReductions[0];
5851 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5852 if (Part == NumParts - 1) {
5854 {Acc, PartialReductions[Part]});
5857 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5861 MI.eraseFromParent();
5867 unsigned int TypeIdx,
5869 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5870 MI.getFirst3RegLLTs();
5871 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5875 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5876 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5877 "Unexpected vecreduce opcode");
5878 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5879 ? TargetOpcode::G_FADD
5880 : TargetOpcode::G_FMUL;
5883 unsigned NumParts = SrcTy.getNumElements();
5886 for (
unsigned i = 0; i < NumParts; i++)
5887 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5891 MI.eraseFromParent();
5898 unsigned ScalarOpc) {
5906 while (SplitSrcs.
size() > 1) {
5908 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
5916 SplitSrcs = std::move(PartialRdxs);
5920 MI.getOperand(1).setReg(SplitSrcs[0]);
5927 const LLT HalfTy,
const LLT AmtTy) {
5929 Register InL = MRI.createGenericVirtualRegister(HalfTy);
5930 Register InH = MRI.createGenericVirtualRegister(HalfTy);
5934 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
5935 MI.eraseFromParent();
5941 unsigned VTBits = 2 * NVTBits;
5944 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
5945 if (Amt.
ugt(VTBits)) {
5947 }
else if (Amt.
ugt(NVTBits)) {
5950 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5951 }
else if (Amt == NVTBits) {
5959 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5962 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
5963 if (Amt.
ugt(VTBits)) {
5965 }
else if (Amt.
ugt(NVTBits)) {
5967 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5969 }
else if (Amt == NVTBits) {
5973 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
5975 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
5977 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5983 if (Amt.
ugt(VTBits)) {
5985 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5986 }
else if (Amt.
ugt(NVTBits)) {
5988 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5990 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5991 }
else if (Amt == NVTBits) {
5994 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5996 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
5998 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6000 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6007 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6008 MI.eraseFromParent();
6024 LLT DstTy = MRI.getType(DstReg);
6029 LLT ShiftAmtTy = MRI.getType(Amt);
6031 if (DstEltSize % 2 != 0)
6047 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6058 const unsigned NewBitSize = DstEltSize / 2;
6070 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6072 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6073 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6076 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6077 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6079 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6084 switch (
MI.getOpcode()) {
6085 case TargetOpcode::G_SHL: {
6087 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6089 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6090 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6091 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6094 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6095 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6097 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6099 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6101 ResultRegs[0] =
Lo.getReg(0);
6102 ResultRegs[1] =
Hi.getReg(0);
6105 case TargetOpcode::G_LSHR:
6106 case TargetOpcode::G_ASHR: {
6108 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6110 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6111 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6112 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6116 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6119 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6120 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6122 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6126 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6128 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6130 ResultRegs[0] =
Lo.getReg(0);
6131 ResultRegs[1] =
Hi.getReg(0);
6138 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6139 MI.eraseFromParent();
6148 LLT TargetTy,
LLT ShiftAmtTy) {
6151 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6153 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6154 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6155 const bool NeedsInterWordShift = ShiftBits != 0;
6158 case TargetOpcode::G_SHL: {
6161 if (PartIdx < ShiftWords)
6164 unsigned SrcIdx = PartIdx - ShiftWords;
6165 if (!NeedsInterWordShift)
6166 return SrcParts[SrcIdx];
6171 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6175 return Hi.getReg(0);
6178 case TargetOpcode::G_LSHR: {
6179 unsigned SrcIdx = PartIdx + ShiftWords;
6180 if (SrcIdx >= NumParts)
6182 if (!NeedsInterWordShift)
6183 return SrcParts[SrcIdx];
6187 if (SrcIdx + 1 < NumParts) {
6188 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6192 return Lo.getReg(0);
6195 case TargetOpcode::G_ASHR: {
6197 unsigned SrcIdx = PartIdx + ShiftWords;
6198 if (SrcIdx >= NumParts)
6200 if (!NeedsInterWordShift)
6201 return SrcParts[SrcIdx];
6206 (SrcIdx == NumParts - 1)
6210 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6232 unsigned MainOpcode =
6233 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6237 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6246 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6247 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6249 auto IsZeroBitShift =
6257 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6258 : TargetOpcode::G_SHL;
6261 auto TargetBitsConst =
6263 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6268 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6273 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6275 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6279 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6292 LLT DstTy = MRI.getType(DstReg);
6296 const unsigned NumParts = DstBits / TargetBits;
6298 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6308 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6309 MI.eraseFromParent();
6314 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6315 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6321 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6325 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6328 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6329 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6333 for (
unsigned I = 0;
I < NumParts; ++
I)
6335 Params, TargetTy, ShiftAmtTy);
6337 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6338 MI.eraseFromParent();
6347 LLT DstTy = MRI.getType(DstReg);
6348 LLT ShiftAmtTy = MRI.getType(AmtReg);
6352 const unsigned NumParts = DstBits / TargetBits;
6354 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6371 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6383 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6384 auto TargetBitsLog2Const =
6385 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6386 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6389 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6391 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6399 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6400 auto TargetBitsMinusOneConst =
6401 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6403 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6404 TargetBitsMinusOneConst)
6407 FillValue = ZeroReg;
6415 for (
unsigned I = 0;
I < NumParts; ++
I) {
6417 Register InBoundsResult = FillValue;
6427 for (
unsigned K = 0; K < NumParts; ++K) {
6428 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6430 WordShift, WordShiftKConst);
6442 switch (
MI.getOpcode()) {
6443 case TargetOpcode::G_SHL:
6444 MainSrcIdx = (int)
I - (
int)K;
6445 CarrySrcIdx = MainSrcIdx - 1;
6447 case TargetOpcode::G_LSHR:
6448 case TargetOpcode::G_ASHR:
6449 MainSrcIdx = (int)
I + (
int)K;
6450 CarrySrcIdx = MainSrcIdx + 1;
6458 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6459 Register MainOp = SrcParts[MainSrcIdx];
6463 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6464 CarryOp = SrcParts[CarrySrcIdx];
6465 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6466 CarrySrcIdx >= (
int)NumParts)
6467 CarryOp = FillValue;
6473 ResultForK = FillValue;
6479 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6486 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6490 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6491 MI.eraseFromParent();
6498 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6501 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6516 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6521 "getNeutralElementForVecReduce called with invalid opcode!");
6522 case TargetOpcode::G_VECREDUCE_ADD:
6523 case TargetOpcode::G_VECREDUCE_OR:
6524 case TargetOpcode::G_VECREDUCE_XOR:
6525 case TargetOpcode::G_VECREDUCE_UMAX:
6527 case TargetOpcode::G_VECREDUCE_MUL:
6529 case TargetOpcode::G_VECREDUCE_AND:
6530 case TargetOpcode::G_VECREDUCE_UMIN:
6533 case TargetOpcode::G_VECREDUCE_SMAX:
6536 case TargetOpcode::G_VECREDUCE_SMIN:
6539 case TargetOpcode::G_VECREDUCE_FADD:
6541 case TargetOpcode::G_VECREDUCE_FMUL:
6543 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6544 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6545 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6546 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6554 unsigned Opc =
MI.getOpcode();
6556 case TargetOpcode::G_IMPLICIT_DEF:
6557 case TargetOpcode::G_LOAD: {
6565 case TargetOpcode::G_STORE:
6572 case TargetOpcode::G_AND:
6573 case TargetOpcode::G_OR:
6574 case TargetOpcode::G_XOR:
6575 case TargetOpcode::G_ADD:
6576 case TargetOpcode::G_SUB:
6577 case TargetOpcode::G_MUL:
6578 case TargetOpcode::G_FADD:
6579 case TargetOpcode::G_FSUB:
6580 case TargetOpcode::G_FMUL:
6581 case TargetOpcode::G_FDIV:
6582 case TargetOpcode::G_FCOPYSIGN:
6583 case TargetOpcode::G_UADDSAT:
6584 case TargetOpcode::G_USUBSAT:
6585 case TargetOpcode::G_SADDSAT:
6586 case TargetOpcode::G_SSUBSAT:
6587 case TargetOpcode::G_SMIN:
6588 case TargetOpcode::G_SMAX:
6589 case TargetOpcode::G_UMIN:
6590 case TargetOpcode::G_UMAX:
6591 case TargetOpcode::G_FMINNUM:
6592 case TargetOpcode::G_FMAXNUM:
6593 case TargetOpcode::G_FMINNUM_IEEE:
6594 case TargetOpcode::G_FMAXNUM_IEEE:
6595 case TargetOpcode::G_FMINIMUM:
6596 case TargetOpcode::G_FMAXIMUM:
6597 case TargetOpcode::G_FMINIMUMNUM:
6598 case TargetOpcode::G_FMAXIMUMNUM:
6599 case TargetOpcode::G_STRICT_FADD:
6600 case TargetOpcode::G_STRICT_FSUB:
6601 case TargetOpcode::G_STRICT_FMUL:
6602 case TargetOpcode::G_SHL:
6603 case TargetOpcode::G_ASHR:
6604 case TargetOpcode::G_LSHR: {
6612 case TargetOpcode::G_FMA:
6613 case TargetOpcode::G_STRICT_FMA:
6614 case TargetOpcode::G_FSHR:
6615 case TargetOpcode::G_FSHL: {
6624 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6625 case TargetOpcode::G_EXTRACT:
6632 case TargetOpcode::G_INSERT:
6633 case TargetOpcode::G_INSERT_VECTOR_ELT:
6634 case TargetOpcode::G_FREEZE:
6635 case TargetOpcode::G_FNEG:
6636 case TargetOpcode::G_FABS:
6637 case TargetOpcode::G_FSQRT:
6638 case TargetOpcode::G_FCEIL:
6639 case TargetOpcode::G_FFLOOR:
6640 case TargetOpcode::G_FNEARBYINT:
6641 case TargetOpcode::G_FRINT:
6642 case TargetOpcode::G_INTRINSIC_ROUND:
6643 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6644 case TargetOpcode::G_INTRINSIC_TRUNC:
6645 case TargetOpcode::G_BITREVERSE:
6646 case TargetOpcode::G_BSWAP:
6647 case TargetOpcode::G_FCANONICALIZE:
6648 case TargetOpcode::G_SEXT_INREG:
6649 case TargetOpcode::G_ABS:
6650 case TargetOpcode::G_CTLZ:
6651 case TargetOpcode::G_CTPOP:
6659 case TargetOpcode::G_SELECT: {
6660 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6662 if (!CondTy.isScalar() ||
6668 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6670 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6675 if (CondTy.isVector())
6685 case TargetOpcode::G_UNMERGE_VALUES:
6687 case TargetOpcode::G_PHI:
6689 case TargetOpcode::G_SHUFFLE_VECTOR:
6691 case TargetOpcode::G_BUILD_VECTOR: {
6693 for (
auto Op :
MI.uses()) {
6701 MIRBuilder.buildDeleteTrailingVectorElements(
6702 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6703 MI.eraseFromParent();
6706 case TargetOpcode::G_SEXT:
6707 case TargetOpcode::G_ZEXT:
6708 case TargetOpcode::G_ANYEXT:
6709 case TargetOpcode::G_TRUNC:
6710 case TargetOpcode::G_FPTRUNC:
6711 case TargetOpcode::G_FPEXT:
6712 case TargetOpcode::G_FPTOSI:
6713 case TargetOpcode::G_FPTOUI:
6714 case TargetOpcode::G_FPTOSI_SAT:
6715 case TargetOpcode::G_FPTOUI_SAT:
6716 case TargetOpcode::G_SITOFP:
6717 case TargetOpcode::G_UITOFP: {
6725 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6729 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6737 case TargetOpcode::G_ICMP:
6738 case TargetOpcode::G_FCMP: {
6747 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6752 case TargetOpcode::G_BITCAST: {
6756 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6757 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6773 case TargetOpcode::G_VECREDUCE_FADD:
6774 case TargetOpcode::G_VECREDUCE_FMUL:
6775 case TargetOpcode::G_VECREDUCE_ADD:
6776 case TargetOpcode::G_VECREDUCE_MUL:
6777 case TargetOpcode::G_VECREDUCE_AND:
6778 case TargetOpcode::G_VECREDUCE_OR:
6779 case TargetOpcode::G_VECREDUCE_XOR:
6780 case TargetOpcode::G_VECREDUCE_SMAX:
6781 case TargetOpcode::G_VECREDUCE_SMIN:
6782 case TargetOpcode::G_VECREDUCE_UMAX:
6783 case TargetOpcode::G_VECREDUCE_UMIN: {
6784 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6786 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6787 auto NeutralElement = getNeutralElementForVecReduce(
6793 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6794 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6795 NeutralElement, Idx);
6799 MO.
setReg(NewVec.getReg(0));
6811 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6813 unsigned MaskNumElts = Mask.size();
6814 unsigned SrcNumElts = SrcTy.getNumElements();
6817 if (MaskNumElts == SrcNumElts)
6820 if (MaskNumElts < SrcNumElts) {
6828 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6829 MI.getOperand(1).getReg(),
6830 MI.getOperand(2).getReg(), NewMask);
6831 MI.eraseFromParent();
6836 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6837 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6845 MOps1[0] =
MI.getOperand(1).getReg();
6846 MOps2[0] =
MI.getOperand(2).getReg();
6848 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6849 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6853 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6855 if (Idx >=
static_cast<int>(SrcNumElts))
6856 Idx += PaddedMaskNumElts - SrcNumElts;
6861 if (MaskNumElts != PaddedMaskNumElts) {
6863 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6866 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6868 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6873 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6876 MI.eraseFromParent();
6882 unsigned int TypeIdx,
LLT MoreTy) {
6883 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6885 unsigned NumElts = DstTy.getNumElements();
6888 if (DstTy.isVector() && Src1Ty.isVector() &&
6889 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6897 if (DstTy != Src1Ty || DstTy != Src2Ty)
6905 for (
unsigned I = 0;
I != NumElts; ++
I) {
6907 if (Idx <
static_cast<int>(NumElts))
6910 NewMask[
I] = Idx - NumElts + WidenNumElts;
6914 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6915 MI.getOperand(1).getReg(),
6916 MI.getOperand(2).getReg(), NewMask);
6917 MI.eraseFromParent();
6926 unsigned SrcParts = Src1Regs.
size();
6927 unsigned DstParts = DstRegs.
size();
6929 unsigned DstIdx = 0;
6931 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
6932 DstRegs[DstIdx] = FactorSum;
6937 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
6939 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
6940 i <= std::min(DstIdx, SrcParts - 1); ++i) {
6942 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
6946 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
6947 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
6949 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
6959 if (DstIdx != DstParts - 1) {
6960 MachineInstrBuilder Uaddo =
6961 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
6962 FactorSum = Uaddo.
getReg(0);
6963 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
6964 for (
unsigned i = 2; i < Factors.
size(); ++i) {
6965 MachineInstrBuilder Uaddo =
6966 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
6967 FactorSum = Uaddo.
getReg(0);
6968 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
6969 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
6973 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
6974 for (
unsigned i = 2; i < Factors.
size(); ++i)
6975 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
6978 CarrySumPrevDstIdx = CarrySum;
6979 DstRegs[DstIdx] = FactorSum;
6991 LLT DstType = MRI.getType(DstReg);
6993 if (DstType.isVector())
6996 unsigned Opcode =
MI.getOpcode();
6997 unsigned OpO, OpE, OpF;
6999 case TargetOpcode::G_SADDO:
7000 case TargetOpcode::G_SADDE:
7001 case TargetOpcode::G_UADDO:
7002 case TargetOpcode::G_UADDE:
7003 case TargetOpcode::G_ADD:
7004 OpO = TargetOpcode::G_UADDO;
7005 OpE = TargetOpcode::G_UADDE;
7006 OpF = TargetOpcode::G_UADDE;
7007 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7008 OpF = TargetOpcode::G_SADDE;
7010 case TargetOpcode::G_SSUBO:
7011 case TargetOpcode::G_SSUBE:
7012 case TargetOpcode::G_USUBO:
7013 case TargetOpcode::G_USUBE:
7014 case TargetOpcode::G_SUB:
7015 OpO = TargetOpcode::G_USUBO;
7016 OpE = TargetOpcode::G_USUBE;
7017 OpF = TargetOpcode::G_USUBE;
7018 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7019 OpF = TargetOpcode::G_SSUBE;
7026 unsigned NumDefs =
MI.getNumExplicitDefs();
7027 Register Src1 =
MI.getOperand(NumDefs).getReg();
7028 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7031 CarryDst =
MI.getOperand(1).getReg();
7032 if (
MI.getNumOperands() == NumDefs + 3)
7033 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7035 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7036 LLT LeftoverTy, DummyTy;
7038 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7043 int NarrowParts = Src1Regs.
size();
7044 Src1Regs.
append(Src1Left);
7045 Src2Regs.
append(Src2Left);
7048 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7050 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7053 if (i == e - 1 && CarryDst)
7054 CarryOut = CarryDst;
7056 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7059 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7060 {Src1Regs[i], Src2Regs[i]});
7061 }
else if (i == e - 1) {
7062 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7063 {Src1Regs[i], Src2Regs[i], CarryIn});
7065 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7066 {Src1Regs[i], Src2Regs[i], CarryIn});
7072 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7073 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7074 ArrayRef(DstRegs).drop_front(NarrowParts));
7076 MI.eraseFromParent();
7082 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7084 LLT Ty = MRI.getType(DstReg);
7088 unsigned Size = Ty.getSizeInBits();
7090 if (
Size % NarrowSize != 0)
7093 unsigned NumParts =
Size / NarrowSize;
7094 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7095 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7101 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7105 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7106 MI.eraseFromParent();
7116 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7119 LLT SrcTy = MRI.getType(Src);
7130 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7143 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7146 if (SizeOp1 % NarrowSize != 0)
7148 int NumParts = SizeOp1 / NarrowSize;
7151 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7155 uint64_t OpStart =
MI.getOperand(2).getImm();
7156 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7157 for (
int i = 0; i < NumParts; ++i) {
7158 unsigned SrcStart = i * NarrowSize;
7160 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7163 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7171 int64_t ExtractOffset;
7173 if (OpStart < SrcStart) {
7175 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7177 ExtractOffset = OpStart - SrcStart;
7178 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7182 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7184 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7185 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7192 if (MRI.getType(DstReg).isVector())
7193 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7194 else if (DstRegs.
size() > 1)
7195 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7198 MI.eraseFromParent();
7210 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7212 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7215 SrcRegs.
append(LeftoverRegs);
7219 uint64_t OpStart =
MI.getOperand(3).getImm();
7220 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7221 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7222 unsigned DstStart =
I * NarrowSize;
7224 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7232 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7234 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7238 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7246 int64_t ExtractOffset, InsertOffset;
7248 if (OpStart < DstStart) {
7250 ExtractOffset = DstStart - OpStart;
7251 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7253 InsertOffset = OpStart - DstStart;
7256 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7260 if (ExtractOffset != 0 || SegSize != OpSize) {
7262 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7263 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7266 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7267 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7275 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7278 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7280 MI.eraseFromParent();
7288 LLT DstTy = MRI.getType(DstReg);
7290 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7296 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7297 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7301 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7302 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7305 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7306 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7307 {Src0Regs[I], Src1Regs[I]});
7311 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7314 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7315 DstLeftoverRegs.
push_back(Inst.getReg(0));
7318 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7319 LeftoverTy, DstLeftoverRegs);
7321 MI.eraseFromParent();
7331 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7333 LLT DstTy = MRI.getType(DstReg);
7338 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7339 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7340 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7342 MI.eraseFromParent();
7352 Register CondReg =
MI.getOperand(1).getReg();
7353 LLT CondTy = MRI.getType(CondReg);
7358 LLT DstTy = MRI.getType(DstReg);
7364 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7365 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7369 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7370 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7373 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7375 CondReg, Src1Regs[
I], Src2Regs[
I]);
7379 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7381 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7385 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7386 LeftoverTy, DstLeftoverRegs);
7388 MI.eraseFromParent();
7398 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7401 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7402 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7405 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7407 auto C_0 =
B.buildConstant(NarrowTy, 0);
7409 UnmergeSrc.getReg(1), C_0);
7410 auto LoCTLZ = IsUndef ?
7411 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7412 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7413 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7414 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7415 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7416 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7418 MI.eraseFromParent();
7431 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7434 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7435 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7438 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7440 auto C_0 =
B.buildConstant(NarrowTy, 0);
7442 UnmergeSrc.getReg(0), C_0);
7443 auto HiCTTZ = IsUndef ?
7444 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7445 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7446 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7447 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7448 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7449 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7451 MI.eraseFromParent();
7464 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7467 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7468 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7470 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7471 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7472 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7474 MI.eraseFromParent();
7489 LLT ExpTy = MRI.getType(ExpReg);
7494 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7495 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7496 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7497 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7499 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7501 MI.getOperand(2).setReg(Trunc.getReg(0));
7508 unsigned Opc =
MI.getOpcode();
7511 auto QAction = LI.getAction(Q).Action;
7517 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7520 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7524 case TargetOpcode::G_CTLZ: {
7525 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7526 unsigned Len = SrcTy.getSizeInBits();
7528 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7530 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7531 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7534 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7535 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7536 MI.eraseFromParent();
7552 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7553 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7556 Op = MIBOp.getReg(0);
7561 MI.eraseFromParent();
7564 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7567 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7571 case TargetOpcode::G_CTTZ: {
7572 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7574 unsigned Len = SrcTy.getSizeInBits();
7575 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7578 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7579 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7582 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7583 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7584 MI.eraseFromParent();
7591 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7592 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7594 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7595 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7596 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7597 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7600 MI.eraseFromParent();
7604 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7605 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7609 case TargetOpcode::G_CTPOP: {
7611 LLT Ty = MRI.getType(SrcReg);
7612 unsigned Size = Ty.getSizeInBits();
7620 auto C_1 =
B.buildConstant(Ty, 1);
7621 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7623 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7624 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7625 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7629 auto C_2 =
B.buildConstant(Ty, 2);
7630 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7632 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7633 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7634 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7635 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7642 auto C_4 =
B.buildConstant(Ty, 4);
7643 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7644 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7646 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7647 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7649 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7655 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7657 auto IsMulSupported = [
this](
const LLT Ty) {
7658 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7661 if (IsMulSupported(Ty)) {
7662 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7663 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7665 auto ResTmp = B8Count;
7666 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7667 auto ShiftC =
B.buildConstant(Ty, Shift);
7668 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7669 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7671 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7673 MI.eraseFromParent();
7694 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7695 LLT Ty = MRI.getType(Dst);
7696 LLT ShTy = MRI.getType(Z);
7703 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7704 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7709 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7710 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7714 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7727 MI.eraseFromParent();
7733 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7734 LLT Ty = MRI.getType(Dst);
7735 LLT ShTy = MRI.getType(Z);
7738 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7748 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7749 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7750 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7751 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7752 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7756 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7759 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7762 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7764 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7765 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7766 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7769 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7771 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7773 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7776 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7777 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7782 MI.eraseFromParent();
7793 LLT Ty = MRI.getType(Dst);
7794 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7796 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7797 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7800 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7801 return lowerFunnelShiftAsShifts(
MI);
7805 if (Result == UnableToLegalize)
7806 return lowerFunnelShiftAsShifts(
MI);
7811 auto [Dst, Src] =
MI.getFirst2Regs();
7812 LLT DstTy = MRI.getType(Dst);
7813 LLT SrcTy = MRI.getType(Src);
7817 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7825 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7829 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7833 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7838 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7839 {UnmergeSrc.getReg(0)});
7840 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7841 {UnmergeSrc.getReg(1)});
7844 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7846 MI.eraseFromParent();
7863 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7867 LLT DstTy = MRI.getType(DstReg);
7868 LLT SrcTy = MRI.getType(SrcReg);
7876 SrcTy.getElementCount().divideCoefficientBy(2));
7889 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7901 MI.eraseFromParent();
7910 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7911 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
7912 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7913 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7914 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
7915 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
7916 MI.eraseFromParent();
7921 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7923 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
7924 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7929 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7930 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
7932 return lowerRotateWithReverseRotate(
MI);
7935 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7936 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7937 bool IsFShLegal =
false;
7938 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
7939 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
7943 MI.eraseFromParent();
7948 return buildFunnelShift(FShOpc, Dst, Src, Amt);
7951 return buildFunnelShift(RevFsh, Dst, Src, Amt);
7956 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
7957 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
7958 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
7964 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
7965 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
7967 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
7973 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
7974 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
7976 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
7978 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
7982 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
7983 MI.eraseFromParent();
7991 auto [Dst, Src] =
MI.getFirst2Regs();
7996 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8024 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8037 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8041 MI.eraseFromParent();
8049 auto [Dst, Src] =
MI.getFirst2Regs();
8054 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8067 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8069 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8074 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8076 MI.eraseFromParent();
8084 auto [Dst, Src] =
MI.getFirst2Regs();
8088 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8099 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8100 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8102 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8109 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8110 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8111 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8113 MI.eraseFromParent();
8123 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8129 MI.eraseFromParent();
8134 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8137 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8138 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8139 MIRBuilder.buildSelect(Dst, Src, True, False);
8140 MI.eraseFromParent();
8144 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8164 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8171 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8172 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8173 MIRBuilder.buildSelect(Dst, Src, True, False);
8174 MI.eraseFromParent();
8178 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8201 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8202 MI.eraseFromParent();
8210 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8214 if (SrcTy !=
S64 && SrcTy !=
S32)
8216 if (DstTy !=
S32 && DstTy !=
S64)
8243 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8245 MI.eraseFromParent();
8250 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8255 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8262 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8264 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8265 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8267 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8268 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8270 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8272 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8273 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8274 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8277 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8278 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8279 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8281 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8284 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8289 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8290 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8296 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8298 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8299 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8301 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8306 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8307 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8309 MI.eraseFromParent();
8315 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8317 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8318 unsigned SatWidth = DstTy.getScalarSizeInBits();
8322 APInt MinInt, MaxInt;
8345 if (AreExactFloatBounds) {
8347 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8349 SrcTy.changeElementSize(1), Src, MaxC);
8350 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8352 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8362 MI.eraseFromParent();
8367 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8369 DstTy.changeElementSize(1), Src, Src);
8372 MI.eraseFromParent();
8379 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8388 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8399 MI.eraseFromParent();
8405 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8407 DstTy.changeElementSize(1), Src, Src);
8409 MI.eraseFromParent();
8419 auto [Dst, Src] =
MI.getFirst2Regs();
8421 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8423 if (MRI.getType(Src).isVector())
8427 unsigned Flags =
MI.getFlags();
8430 MI.eraseFromParent();
8434 const unsigned ExpMask = 0x7ff;
8435 const unsigned ExpBiasf64 = 1023;
8436 const unsigned ExpBiasf16 = 15;
8465 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8525 MI.eraseFromParent();
8531 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8535 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8542 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8543 LLT Ty = MRI.getType(Dst);
8545 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8546 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8547 MI.eraseFromParent();
8553 case TargetOpcode::G_SMIN:
8555 case TargetOpcode::G_SMAX:
8557 case TargetOpcode::G_UMIN:
8559 case TargetOpcode::G_UMAX:
8567 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8572 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8573 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8575 MI.eraseFromParent();
8584 LLT DstTy = MRI.getType(Dst);
8585 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8595 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8596 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8598 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8601 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8602 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8603 if (TLI.preferSelectsOverBooleanArithmetic(
8606 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8607 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8609 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8610 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8616 unsigned BoolExtOp =
8618 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8619 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8623 MI.eraseFromParent();
8629 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8630 const int Src0Size = Src0Ty.getScalarSizeInBits();
8631 const int Src1Size = Src1Ty.getScalarSizeInBits();
8636 auto NotSignBitMask =
MIRBuilder.buildConstant(
8641 if (Src0Ty == Src1Ty) {
8642 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8643 }
else if (Src0Size > Src1Size) {
8644 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8645 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8646 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8647 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8649 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8650 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8651 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8652 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8658 unsigned Flags =
MI.getFlags();
8665 MI.eraseFromParent();
8676 switch (
MI.getOpcode()) {
8677 case TargetOpcode::G_FMINNUM:
8678 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8680 case TargetOpcode::G_FMINIMUMNUM:
8681 NewOp = TargetOpcode::G_FMINNUM;
8683 case TargetOpcode::G_FMAXNUM:
8684 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8686 case TargetOpcode::G_FMAXIMUMNUM:
8687 NewOp = TargetOpcode::G_FMAXNUM;
8693 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8694 LLT Ty = MRI.getType(Dst);
8704 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8707 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8712 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8713 MI.eraseFromParent();
8720 LLT Ty = MRI.getType(DstReg);
8721 unsigned Flags =
MI.getFlags();
8726 MI.eraseFromParent();
8732 auto [DstReg,
X] =
MI.getFirst2Regs();
8733 const unsigned Flags =
MI.getFlags();
8734 const LLT Ty = MRI.getType(DstReg);
8746 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8748 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8753 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8754 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8755 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8756 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8758 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8760 MI.eraseFromParent();
8765 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8766 unsigned Flags =
MI.getFlags();
8767 LLT Ty = MRI.getType(DstReg);
8774 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8775 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8778 SrcReg, Zero, Flags);
8780 SrcReg, Trunc, Flags);
8784 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8785 MI.eraseFromParent();
8791 const unsigned NumOps =
MI.getNumOperands();
8792 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8793 unsigned PartSize = Src0Ty.getSizeInBits();
8798 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8799 const unsigned Offset = (
I - 1) * PartSize;
8802 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8805 MRI.createGenericVirtualRegister(WideTy);
8808 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8809 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8810 ResultReg = NextResult;
8813 if (DstTy.isPointer()) {
8814 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8815 DstTy.getAddressSpace())) {
8823 MI.eraseFromParent();
8829 const unsigned NumDst =
MI.getNumOperands() - 1;
8830 Register SrcReg =
MI.getOperand(NumDst).getReg();
8831 Register Dst0Reg =
MI.getOperand(0).getReg();
8832 LLT DstTy = MRI.getType(Dst0Reg);
8841 LLT IntTy = MRI.getType(SrcReg);
8846 unsigned Offset = DstSize;
8847 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
8849 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
8853 MI.eraseFromParent();
8872 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
8873 InsertVal =
MI.getOperand(2).getReg();
8875 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
8877 LLT VecTy = MRI.getType(SrcVec);
8887 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
8888 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
8890 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
8893 MI.eraseFromParent();
8898 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
8909 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
8916 int64_t
Offset = IdxVal * EltBytes;
8927 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
8930 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
8932 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
8935 MI.eraseFromParent();
8941 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
8942 MI.getFirst3RegLLTs();
8950 for (
int Idx : Mask) {
8952 if (!Undef.isValid())
8953 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
8958 if (Src0Ty.isScalar()) {
8959 BuildVec.
push_back(Idx == 0 ? Src0Reg : Src1Reg);
8961 int NumElts = Src0Ty.getNumElements();
8962 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
8963 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
8964 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
8965 auto Extract =
MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK);
8970 if (DstTy.isVector())
8971 MIRBuilder.buildBuildVector(DstReg, BuildVec);
8974 MI.eraseFromParent();
8980 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
8981 MI.getFirst4RegLLTs();
8983 if (VecTy.isScalableVector())
8999 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9002 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9005 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9008 std::optional<APInt> PassthruSplatVal =
9011 if (PassthruSplatVal.has_value()) {
9013 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9014 }
else if (HasPassthru) {
9015 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9016 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9022 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9026 unsigned NumElmts = VecTy.getNumElements();
9027 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9029 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9032 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9035 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9040 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9042 if (HasPassthru &&
I == NumElmts - 1) {
9045 auto AllLanesSelected =
MIRBuilder.buildICmp(
9047 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9048 {OutPos, EndOfVector});
9052 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9054 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9059 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9061 MI.eraseFromParent();
9072 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9078 if (Alignment >
Align(1)) {
9081 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9090 const auto &MF = *
MI.getMF();
9096 Register AllocSize =
MI.getOperand(1).getReg();
9099 LLT PtrTy = MRI.getType(Dst);
9100 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9107 MI.eraseFromParent();
9113 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9118 MI.eraseFromParent();
9124 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9129 MI.eraseFromParent();
9135 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9136 unsigned Offset =
MI.getOperand(2).getImm();
9139 if (SrcTy.isVector()) {
9140 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9141 unsigned DstSize = DstTy.getSizeInBits();
9143 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9144 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9146 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9150 for (
unsigned Idx =
Offset / SrcEltSize;
9151 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9152 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9154 if (SubVectorElts.
size() == 1)
9155 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9157 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9159 MI.eraseFromParent();
9164 if (DstTy.isScalar() &&
9165 (SrcTy.isScalar() ||
9166 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9167 LLT SrcIntTy = SrcTy;
9168 if (!SrcTy.isScalar()) {
9170 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9177 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9181 MI.eraseFromParent();
9189 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9192 LLT DstTy = MRI.getType(Src);
9193 LLT InsertTy = MRI.getType(InsertSrc);
9201 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9203 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9207 for (; Idx <
Offset / EltSize; ++Idx) {
9208 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9213 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9214 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9216 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9225 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9228 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9229 MI.eraseFromParent();
9243 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9247 LLT IntDstTy = DstTy;
9251 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9256 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9262 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9268 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9269 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9270 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9273 MI.eraseFromParent();
9279 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9280 MI.getFirst4RegLLTs();
9281 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9284 LLT BoolTy = Dst1Ty;
9286 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9303 auto ResultLowerThanLHS =
9308 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9311 MI.eraseFromParent();
9317 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9318 const LLT Ty = MRI.getType(Res);
9321 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
9322 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9323 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
9334 MI.eraseFromParent();
9339 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
9340 const LLT Ty = MRI.getType(Res);
9343 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
9344 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
9345 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
9350 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
9355 MI.eraseFromParent();
9361 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9362 LLT Ty = MRI.getType(Res);
9366 switch (
MI.getOpcode()) {
9369 case TargetOpcode::G_UADDSAT:
9372 BaseOp = TargetOpcode::G_ADD;
9374 case TargetOpcode::G_SADDSAT:
9377 BaseOp = TargetOpcode::G_ADD;
9379 case TargetOpcode::G_USUBSAT:
9382 BaseOp = TargetOpcode::G_SUB;
9384 case TargetOpcode::G_SSUBSAT:
9387 BaseOp = TargetOpcode::G_SUB;
9402 uint64_t NumBits = Ty.getScalarSizeInBits();
9413 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9421 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9426 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9427 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9430 MI.eraseFromParent();
9436 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9437 LLT Ty = MRI.getType(Res);
9441 unsigned OverflowOp;
9442 switch (
MI.getOpcode()) {
9445 case TargetOpcode::G_UADDSAT:
9448 OverflowOp = TargetOpcode::G_UADDO;
9450 case TargetOpcode::G_SADDSAT:
9453 OverflowOp = TargetOpcode::G_SADDO;
9455 case TargetOpcode::G_USUBSAT:
9458 OverflowOp = TargetOpcode::G_USUBO;
9460 case TargetOpcode::G_SSUBSAT:
9463 OverflowOp = TargetOpcode::G_SSUBO;
9468 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9469 Register Tmp = OverflowRes.getReg(0);
9470 Register Ov = OverflowRes.getReg(1);
9479 uint64_t NumBits = Ty.getScalarSizeInBits();
9480 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9481 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9484 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9492 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9496 MI.eraseFromParent();
9502 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9503 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9504 "Expected shlsat opcode!");
9505 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9506 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9507 LLT Ty = MRI.getType(Res);
9511 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9512 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9521 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9526 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9528 MI.eraseFromParent();
9533 auto [Dst, Src] =
MI.getFirst2Regs();
9534 const LLT Ty = MRI.getType(Src);
9535 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9536 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9539 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9540 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9541 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9542 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9545 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9547 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9548 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9549 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9551 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9552 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9553 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9555 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9556 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9557 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9559 Res.getInstr()->getOperand(0).setReg(Dst);
9561 MI.eraseFromParent();
9568 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9571 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9572 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9573 return B.buildOr(Dst,
LHS,
RHS);
9578 auto [Dst, Src] =
MI.getFirst2Regs();
9579 const LLT SrcTy = MRI.getType(Src);
9580 unsigned Size = SrcTy.getScalarSizeInBits();
9581 unsigned VSize = SrcTy.getSizeInBits();
9584 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9585 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9586 {LLT::fixed_vector(VSize / 8, 8),
9587 LLT::fixed_vector(VSize / 8, 8)}}))) {
9592 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9593 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9594 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9598 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9621 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9625 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9628 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9632 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9636 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9641 MI.eraseFromParent();
9649 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9650 int NameOpIdx = IsRead ? 1 : 0;
9651 int ValRegIndex = IsRead ? 0 : 1;
9653 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9654 const LLT Ty = MRI.getType(ValReg);
9656 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9663 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9664 Fn,
MI.getDebugLoc()));
9668 MI.eraseFromParent();
9677 MI.eraseFromParent();
9683 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9684 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9686 LLT OrigTy = MRI.getType(Result);
9690 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9691 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9693 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9695 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9696 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9699 MI.eraseFromParent();
9705 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9710 MI.eraseFromParent();
9715 MI.eraseFromParent();
9722 unsigned BitSize = SrcTy.getScalarSizeInBits();
9726 if (SrcTy.isVector())
9727 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9728 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9734 APInt ExpMask = Inf;
9740 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9741 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9742 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9743 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9744 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9746 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9750 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9752 LLT DstTyCopy = DstTy;
9754 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9782 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9785 Mask &= ~PartialCheck;
9794 else if (PartialCheck ==
fcZero)
9806 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9807 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9810 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9812 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9813 appendToRes(SubnormalRes);
9820 else if (PartialCheck ==
fcInf)
9825 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9832 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
9833 if (PartialCheck ==
fcNan) {
9837 }
else if (PartialCheck ==
fcQNan) {
9847 Abs, InfWithQnanBitC);
9848 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
9855 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
9857 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
9858 APInt MaxExpMinusOne = ExpMask - ExpLSB;
9861 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
9863 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
9866 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
9867 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
9869 appendToRes(NormalRes);
9873 MI.eraseFromParent();
9879 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
9880 MI.getFirst4RegLLTs();
9882 bool IsEltPtr = DstTy.isPointerOrPointerVector();
9886 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
9887 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
9891 if (MaskTy.isScalar()) {
9899 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
9903 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
9905 if (DstTy.isVector()) {
9907 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
9908 MaskReg = ShufSplat.getReg(0);
9913 }
else if (!DstTy.isVector()) {
9918 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
9922 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
9923 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
9924 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
9931 MI.eraseFromParent();
9937 unsigned Opcode =
MI.getOpcode();
9940 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
9941 : TargetOpcode::G_UDIV,
9942 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9944 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
9945 : TargetOpcode::G_UREM,
9946 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9947 MI.eraseFromParent();
9957 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
9961 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
9964 MI.eraseFromParent();
9975 LLT Ty = MRI.getType(SrcReg);
9979 MI.eraseFromParent();
9986 Register DestReg =
MI.getOperand(0).getReg();
9988 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
9992 MI.eraseFromParent();
9998 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
9999 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10000 "Expected G_ABDS or G_ABDU instruction");
10002 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10003 LLT Ty = MRI.getType(LHS);
10013 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10015 MI.eraseFromParent();
10021 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10022 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10023 "Expected G_ABDS or G_ABDU instruction");
10025 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10026 LLT Ty = MRI.getType(LHS);
10031 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10032 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10033 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10035 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10036 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10038 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10040 MI.eraseFromParent();
10045 Register SrcReg =
MI.getOperand(1).getReg();
10046 Register DstReg =
MI.getOperand(0).getReg();
10048 LLT Ty = MRI.getType(DstReg);
10056 MI.eraseFromParent();
10062 Register SrcReg =
MI.getOperand(1).getReg();
10063 LLT SrcTy = MRI.getType(SrcReg);
10064 LLT DstTy = MRI.getType(SrcReg);
10067 if (SrcTy.isScalar()) {
10072 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10083 Register ListPtr =
MI.getOperand(1).getReg();
10084 LLT PtrTy = MRI.getType(ListPtr);
10091 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10093 const Align A(
MI.getOperand(2).getImm());
10095 if (
A > TLI.getMinStackArgumentAlignment()) {
10097 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10098 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10099 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10100 VAList = AndDst.getReg(0);
10107 LLT LLTTy = MRI.getType(Dst);
10110 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10111 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10116 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10118 Align EltAlignment =
DL.getABITypeAlign(Ty);
10121 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10123 MI.eraseFromParent();
10138 unsigned Limit,
const MemOp &
Op,
10139 unsigned DstAS,
unsigned SrcAS,
10140 const AttributeList &FuncAttributes,
10142 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10152 if (
Op.isFixedDstAlign())
10153 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10156 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10160 unsigned NumMemOps = 0;
10163 unsigned TySize = Ty.getSizeInBytes();
10164 while (TySize >
Size) {
10173 assert(NewTySize > 0 &&
"Could not find appropriate type");
10180 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10182 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10188 TySize = NewTySize;
10192 if (++NumMemOps > Limit)
10195 MemOps.push_back(Ty);
10205 unsigned NumBits = Ty.getScalarSizeInBits();
10207 if (!Ty.isVector() && ValVRegAndVal) {
10208 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10216 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10237 uint64_t KnownLen,
Align Alignment,
10239 auto &MF = *
MI.getParent()->getParent();
10244 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10246 bool DstAlignCanChange =
false;
10250 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10252 DstAlignCanChange =
true;
10254 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10255 std::vector<LLT> MemOps;
10257 const auto &DstMMO = **
MI.memoperands_begin();
10258 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10261 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10272 if (DstAlignCanChange) {
10275 Align NewAlign =
DL.getABITypeAlign(IRTy);
10276 if (NewAlign > Alignment) {
10277 Alignment = NewAlign;
10285 MachineIRBuilder MIB(
MI);
10287 LLT LargestTy = MemOps[0];
10288 for (
unsigned i = 1; i < MemOps.size(); i++)
10290 LargestTy = MemOps[i];
10302 LLT PtrTy = MRI.getType(Dst);
10303 unsigned DstOff = 0;
10304 unsigned Size = KnownLen;
10305 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10306 LLT Ty = MemOps[
I];
10308 if (TySize >
Size) {
10311 assert(
I == MemOps.size() - 1 &&
I != 0);
10312 DstOff -= TySize -
Size;
10322 TLI.isTruncateFree(LargestVT, VT))
10323 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10336 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10339 MIB.buildStore(
Value,
Ptr, *StoreMMO);
10344 MI.eraseFromParent();
10350 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10352 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10354 const auto *MMOIt =
MI.memoperands_begin();
10356 bool IsVolatile =
MemOp->isVolatile();
10362 "inline memcpy with dynamic size is not yet supported");
10363 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10364 if (KnownLen == 0) {
10365 MI.eraseFromParent();
10369 const auto &DstMMO = **
MI.memoperands_begin();
10370 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10371 Align DstAlign = DstMMO.getBaseAlign();
10372 Align SrcAlign = SrcMMO.getBaseAlign();
10374 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10381 Align SrcAlign,
bool IsVolatile) {
10382 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10383 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10384 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10391 Align SrcAlign,
bool IsVolatile) {
10392 auto &MF = *
MI.getParent()->getParent();
10397 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10399 bool DstAlignCanChange =
false;
10401 Align Alignment = std::min(DstAlign, SrcAlign);
10405 DstAlignCanChange =
true;
10411 std::vector<LLT> MemOps;
10413 const auto &DstMMO = **
MI.memoperands_begin();
10414 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10420 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10426 if (DstAlignCanChange) {
10429 Align NewAlign =
DL.getABITypeAlign(IRTy);
10434 if (!
TRI->hasStackRealignment(MF))
10436 NewAlign = std::min(NewAlign, *StackAlign);
10438 if (NewAlign > Alignment) {
10439 Alignment = NewAlign;
10447 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10449 MachineIRBuilder MIB(
MI);
10455 unsigned CurrOffset = 0;
10456 unsigned Size = KnownLen;
10457 for (
auto CopyTy : MemOps) {
10460 if (CopyTy.getSizeInBytes() >
Size)
10461 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10472 if (CurrOffset != 0) {
10473 LLT SrcTy = MRI.getType(Src);
10476 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10478 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10482 if (CurrOffset != 0) {
10483 LLT DstTy = MRI.getType(Dst);
10484 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10486 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10487 CurrOffset += CopyTy.getSizeInBytes();
10488 Size -= CopyTy.getSizeInBytes();
10491 MI.eraseFromParent();
10497 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10499 auto &MF = *
MI.getParent()->getParent();
10504 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10506 bool DstAlignCanChange =
false;
10509 Align Alignment = std::min(DstAlign, SrcAlign);
10511 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10513 DstAlignCanChange =
true;
10515 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10516 std::vector<LLT> MemOps;
10518 const auto &DstMMO = **
MI.memoperands_begin();
10519 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10520 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10521 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10528 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10534 if (DstAlignCanChange) {
10537 Align NewAlign =
DL.getABITypeAlign(IRTy);
10542 if (!
TRI->hasStackRealignment(MF))
10543 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10544 NewAlign = std::min(NewAlign, *StackAlign);
10546 if (NewAlign > Alignment) {
10547 Alignment = NewAlign;
10555 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10557 MachineIRBuilder MIB(
MI);
10561 unsigned CurrOffset = 0;
10562 SmallVector<Register, 16> LoadVals;
10563 for (
auto CopyTy : MemOps) {
10570 if (CurrOffset != 0) {
10571 LLT SrcTy = MRI.getType(Src);
10574 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10576 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10577 CurrOffset += CopyTy.getSizeInBytes();
10581 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10582 LLT CopyTy = MemOps[
I];
10588 if (CurrOffset != 0) {
10589 LLT DstTy = MRI.getType(Dst);
10592 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10594 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10597 MI.eraseFromParent();
10603 const unsigned Opc =
MI.getOpcode();
10606 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10607 Opc == TargetOpcode::G_MEMSET) &&
10608 "Expected memcpy like instruction");
10610 auto MMOIt =
MI.memoperands_begin();
10615 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10617 if (
Opc != TargetOpcode::G_MEMSET) {
10618 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10619 MemOp = *(++MMOIt);
10620 SrcAlign =
MemOp->getBaseAlign();
10625 if (!LenVRegAndVal)
10627 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10629 if (KnownLen == 0) {
10630 MI.eraseFromParent();
10634 if (MaxLen && KnownLen > MaxLen)
10637 bool IsVolatile =
MemOp->isVolatile();
10638 if (
Opc == TargetOpcode::G_MEMCPY) {
10639 auto &MF = *
MI.getParent()->getParent();
10642 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10643 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10646 if (
Opc == TargetOpcode::G_MEMMOVE)
10647 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10648 if (
Opc == TargetOpcode::G_MEMSET)
10649 return lowerMemset(
MI, Dst, Src, KnownLen, DstAlign, IsVolatile);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static bool findGISelOptimalMemOpLowering(std::vector< LLT > &MemOps, unsigned Limit, const MemOp &Op, unsigned DstAS, unsigned SrcAS, const AttributeList &FuncAttributes, const TargetLowering &TLI)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static LegalizerHelper::LegalizeResult conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, Type *FromType, LostDebugLocObserver &LocObserver, const TargetLowering &TLI, bool IsSigned=false)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static LegalizerHelper::LegalizeResult simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver)
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static bool shouldLowerMemFuncForSize(const MachineFunction &MF)
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static LegalizerHelper::LegalizeResult createAtomicLibcall(MachineIRBuilder &MIRBuilder, MachineInstr &MI)
static RTLIB::Libcall getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI)
static std::pair< int, int > getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy)
Try to break down OrigTy into NarrowTy sized pieces.
static bool hasSameNumEltsOnAllVectorOperands(GenericMachineInstr &MI, MachineRegisterInfo &MRI, std::initializer_list< unsigned > NonVecOpIndices)
Check that all vector operands have same number of elements.
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg, LLT VecTy)
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, Type *FromType)
static void getUnmergeResults(SmallVectorImpl< Register > &Regs, const MachineInstr &MI)
Append the result registers of G_UNMERGE_VALUES MI to Regs.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
#define RTLIBCASE(LibcallPrefix)
static Type * getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Tracks DebugLocs between checkpoints and verifies that they are transferred.
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file describes how to lower LLVM code to machine code.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
APInt bitcastToAPInt() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
void negate()
Negate this APInt in place.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, unsigned hiBit)
Wrap version of getBitsSet.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Represents a insert subvector.
Register getSubVec() const
Register getBigVec() const
uint64_t getIndexImm() const
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
Represents a threeway compare.
Register getValueReg() const
Get the stored value register.
A base class for all GenericMachineInstrs.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr ElementCount getElementCount() const
constexpr LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr LLT getScalarType() const
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerThreewayCompare(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI)
LLVM_ABI LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI)
Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
LLVM_ABI LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty)
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSSUBE(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerSMULH_UMULH(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerLoad(GAnyLoad &MI)
LLVM_ABI LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerAbsToAddXor(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerFConstant(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerBitreverse(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
Legalize a vector instruction by increasing the number of vector elements involved and ignoring the a...
LLVM_ABI LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy)
Multi-way shift legalization: directly split wide shifts into target-sized parts in a single step,...
LLVM_ABI LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI)
LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI Register buildConstantShiftPart(unsigned Opcode, unsigned PartIdx, unsigned NumParts, ArrayRef< Register > SrcParts, const ShiftParams &Params, LLT TargetTy, LLT ShiftAmtTy)
Generates a single output part for constant shifts using direct indexing.
LLVM_ABI void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by truncating the operand's ty...
LLVM_ABI LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI, unsigned NumElts)
LLVM_ABI LegalizeResult lowerFPTOUI(MachineInstr &MI)
const TargetLowering & getTargetLowering() const
LLVM_ABI LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
LLVM_ABI LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult bitcastInsertSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_INSERT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult lowerUnmergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by replacing the value type.
LLVM_ABI LegalizeResult scalarizeVectorBooleanStore(GStore &MI)
Given a store of a boolean vector, scalarize it.
LLVM_ABI LegalizeResult lowerBitcast(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerReadWriteRegister(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, LLT HalfTy, LLT ShiftAmtTy)
LLVM_ABI LegalizeResult lowerISFPCLASS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFAbs(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerVectorReduction(MachineInstr &MI)
const LegalizerInfo & getLegalizerInfo() const
Expose LegalizerInfo so the clients can re-use.
LLVM_ABI LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult fewerElementsVectorMultiEltType(GenericMachineInstr &MI, unsigned NumElts, std::initializer_list< unsigned > NonVecOpIndices={})
Handles most opcodes.
LLVM_ABI LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarShiftByConstantMultiway(MachineInstr &MI, const APInt &Amt, LLT TargetTy, LLT ShiftAmtTy)
Optimized path for constant shift amounts using static indexing.
LLVM_ABI MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val)
Create a store of Val to a stack temporary and return a load as the same type as Res.
LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ AlreadyLegal
Instruction was already legal and no change was made to the MachineFunction.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFCopySign(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B)
LLVM_ABI LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSADDE(MachineInstr &MI)
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
LLVM_ABI LegalizeResult lowerFunnelShift(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFPTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
LLVM_ABI LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
LLVM_ABI LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerFFloor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult fewerElementsVectorSeqReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize, Align Alignment, LLT PtrTy)
LLVM_ABI LegalizeResult lowerFPTOSI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerUITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerShuffleVector(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerMergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerVECTOR_COMPRESS(MachineInstr &MI)
LLVM_ABI void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by producing a vector with und...
LLVM_ABI LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF32WithSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0)
LLVM_ABI Register coerceToScalar(Register Val)
Cast the given value to an LLT::scalar with an equivalent size.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI LegalizeResult lowerTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBswap(MachineInstr &MI)
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
LLVM_ABI LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const
Return the alignment to use for a stack temporary object with the given type.
LLVM_ABI LegalizeResult lowerConstant(MachineInstr &MI)
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LLVM_ABI LegalizeResult legalizeInstrStep(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Replace MI by a sequence of legal instructions that can implement the same operation.
TypeSize getValue() const
void checkpoint(bool CheckDebugLocs=true)
Call this to indicate that it's a good point to assess whether locations have been lost.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
LLVM_ABI StringRef getString() const
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
LLVM_ABI iterator getFirstTerminatorForward()
Finds the first terminator in a block by scanning forward.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_UREM Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0)
Build and insert integer negation Zero = G_CONSTANT 0 Res = G_SUB Zero, Op0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_UITOFP Src0.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
MachineInstrBuilder buildXor(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_XOR Op0, Op1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
virtual bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *=nullptr) const
Determine if the target supports unaligned memory accesses.
virtual LLT getOptimalMemOpLLT(const MemOp &Op, const AttributeList &) const
LLT returning variant.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const
Returns true if arguments should be sign-extended in lib calls.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
const Triple & getTargetTriple() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const CallLowering * getCallLowering() const
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, DriverKit, XROS, or bridgeOS).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Type * getType() const
All values are typed, get the type of this value.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ Custom
The target wants to do something special with this combination of operand and type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
FunctionAddr VTableAddr Value
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
LLVM_ABI LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver)
Create a libcall to memcpy et al.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI LegalizerHelper::LegalizeResult createLibcall(MachineIRBuilder &MIRBuilder, const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr)
Helper function that creates a libcall to the given Name using the given calling convention CC.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI)
Returns true if Val can be assumed to never be a signaling NaN.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static LLVM_ABI const fltSemantics & IEEEsingle() LLVM_READNONE
static constexpr roundingMode rmNearestTiesToEven
static constexpr roundingMode rmTowardZero
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE
opStatus
IEEE-754R 7: Default exception handling.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
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)