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_FSQRT:
492 case TargetOpcode::G_FRINT:
494 case TargetOpcode::G_FNEARBYINT:
496 case TargetOpcode::G_INTRINSIC_TRUNC:
498 case TargetOpcode::G_INTRINSIC_ROUND:
500 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
502 case TargetOpcode::G_INTRINSIC_LRINT:
504 case TargetOpcode::G_INTRINSIC_LLRINT:
524 AttributeList CallerAttrs =
F.getAttributes();
525 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
526 .removeAttribute(Attribute::NoAlias)
527 .removeAttribute(Attribute::NonNull)
532 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
533 CallerAttrs.hasRetAttr(Attribute::SExt))
544 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
551 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
559 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
562 if (Ret->getNumImplicitOperands() != 1)
565 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
589 Info.OrigRet = Result;
592 (Result.Ty->isVoidTy() ||
598 if (!CLI.lowerCall(MIRBuilder, Info))
601 if (
MI && Info.LoweredTailCall) {
602 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
612 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
613 "Expected instr following MI to be return or debug inst?");
616 Next->eraseFromParent();
617 }
while (
MI->getNextNode());
631 const char *Name = TLI.getLibcallName(
Libcall);
635 return createLibcall(MIRBuilder, Name, Result, Args, CC, LocObserver,
MI);
647 Args.push_back({MO.getReg(), OpType, 0});
649 {
MI.getOperand(0).getReg(), OpType, 0}, Args,
656 MachineFunction &MF = *
MI.getMF();
662 LLT DstTy = MRI.getType(DstSin);
667 unsigned AddrSpace =
DL.getAllocaAddrSpace();
668 MachinePointerInfo PtrInfo;
686 if (LibcallResult != LegalizeResult::Legalized)
694 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
695 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
696 MI.eraseFromParent();
708 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
712 LLT OpLLT =
MRI.getType(Reg);
713 Type *OpTy =
nullptr;
718 Args.push_back({Reg, OpTy, 0});
723 RTLIB::Libcall RTLibcall;
724 unsigned Opc =
MI.getOpcode();
727 case TargetOpcode::G_BZERO:
728 RTLibcall = RTLIB::BZERO;
729 Name = TLI.getLibcallName(RTLibcall);
731 case TargetOpcode::G_MEMCPY:
732 RTLibcall = RTLIB::MEMCPY;
733 Name = TLI.getMemcpyName();
734 Args[0].Flags[0].setReturned();
736 case TargetOpcode::G_MEMMOVE:
737 RTLibcall = RTLIB::MEMMOVE;
738 Name = TLI.getLibcallName(RTLibcall);
739 Args[0].Flags[0].setReturned();
741 case TargetOpcode::G_MEMSET:
742 RTLibcall = RTLIB::MEMSET;
743 Name = TLI.getLibcallName(RTLibcall);
744 Args[0].Flags[0].setReturned();
758 Info.
CallConv = TLI.getLibcallCallingConv(RTLibcall);
762 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
766 if (!CLI.lowerCall(MIRBuilder, Info))
769 if (Info.LoweredTailCall) {
770 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
780 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
781 "Expected instr following MI to be return or debug inst?");
784 Next->eraseFromParent();
785 }
while (
MI.getNextNode());
795 unsigned Opc =
MI.getOpcode();
797 auto &MMO = AtomicMI.getMMO();
798 auto Ordering = MMO.getMergedOrdering();
799 LLT MemType = MMO.getMemoryType();
802 return RTLIB::UNKNOWN_LIBCALL;
804#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
806 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
808 case TargetOpcode::G_ATOMIC_CMPXCHG:
809 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
810 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
811 return getOutlineAtomicHelper(LC, Ordering, MemSize);
813 case TargetOpcode::G_ATOMICRMW_XCHG: {
814 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
815 return getOutlineAtomicHelper(LC, Ordering, MemSize);
817 case TargetOpcode::G_ATOMICRMW_ADD:
818 case TargetOpcode::G_ATOMICRMW_SUB: {
819 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
820 return getOutlineAtomicHelper(LC, Ordering, MemSize);
822 case TargetOpcode::G_ATOMICRMW_AND: {
823 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
824 return getOutlineAtomicHelper(LC, Ordering, MemSize);
826 case TargetOpcode::G_ATOMICRMW_OR: {
827 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
828 return getOutlineAtomicHelper(LC, Ordering, MemSize);
830 case TargetOpcode::G_ATOMICRMW_XOR: {
831 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
832 return getOutlineAtomicHelper(LC, Ordering, MemSize);
835 return RTLIB::UNKNOWN_LIBCALL;
848 unsigned Opc =
MI.getOpcode();
850 case TargetOpcode::G_ATOMIC_CMPXCHG:
851 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
854 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
855 MI.getFirst4RegLLTs();
858 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
859 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
860 NewLLT) =
MI.getFirst5RegLLTs();
870 case TargetOpcode::G_ATOMICRMW_XCHG:
871 case TargetOpcode::G_ATOMICRMW_ADD:
872 case TargetOpcode::G_ATOMICRMW_SUB:
873 case TargetOpcode::G_ATOMICRMW_AND:
874 case TargetOpcode::G_ATOMICRMW_OR:
875 case TargetOpcode::G_ATOMICRMW_XOR: {
876 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
879 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
883 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
898 const char *Name = TLI.getLibcallName(RTLibcall);
908 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall);
913 if (!CLI.lowerCall(MIRBuilder,
Info))
925 case TargetOpcode::G_FPEXT:
927 case TargetOpcode::G_FPTRUNC:
929 case TargetOpcode::G_FPTOSI:
931 case TargetOpcode::G_FPTOUI:
933 case TargetOpcode::G_SITOFP:
935 case TargetOpcode::G_UITOFP:
946 if (FromType->isIntegerTy()) {
948 Arg.
Flags[0].setSExt();
950 Arg.
Flags[0].setZExt();
955 {
MI.getOperand(0).getReg(), ToType, 0}, Arg, LocObserver,
961 RTLIB::Libcall RTLibcall;
962 switch (
MI.getOpcode()) {
963 case TargetOpcode::G_GET_FPENV:
964 RTLibcall = RTLIB::FEGETENV;
966 case TargetOpcode::G_SET_FPENV:
967 case TargetOpcode::G_RESET_FPENV:
968 RTLibcall = RTLIB::FESETENV;
970 case TargetOpcode::G_GET_FPMODE:
971 RTLibcall = RTLIB::FEGETMODE;
973 case TargetOpcode::G_SET_FPMODE:
974 case TargetOpcode::G_RESET_FPMODE:
975 RTLibcall = RTLIB::FESETMODE;
1008 LLT StateTy = MRI.getType(Dst);
1011 MachinePointerInfo TempPtrInfo;
1015 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1021 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1022 LocObserver,
nullptr);
1029 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1048 LLT StateTy = MRI.getType(Src);
1051 MachinePointerInfo TempPtrInfo;
1060 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1065 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1066 LocObserver,
nullptr);
1072static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1074#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1078 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1080 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1082 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1084 llvm_unreachable("unexpected size"); \
1116 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1119 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1126 LLT DstTy = MRI.getType(DstReg);
1127 const auto Cond =
Cmp->getCond();
1132 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1137 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1141 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1148 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1154 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1156 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1169 const auto [OeqLibcall, OeqPred] =
1171 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1173 const auto [UnoLibcall, UnoPred] =
1175 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1190 const auto [OeqLibcall, OeqPred] =
1195 const auto [UnoLibcall, UnoPred] =
1200 if (NotOeq && NotUno)
1219 const auto [InversedLibcall, InversedPred] =
1221 if (!BuildLibcall(InversedLibcall,
1247 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1249 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1252 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1258 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}),
1264 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1266 switch (
MI.getOpcode()) {
1269 case TargetOpcode::G_MUL:
1270 case TargetOpcode::G_SDIV:
1271 case TargetOpcode::G_UDIV:
1272 case TargetOpcode::G_SREM:
1273 case TargetOpcode::G_UREM:
1274 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
1275 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1283 case TargetOpcode::G_FADD:
1284 case TargetOpcode::G_FSUB:
1285 case TargetOpcode::G_FMUL:
1286 case TargetOpcode::G_FDIV:
1287 case TargetOpcode::G_FMA:
1288 case TargetOpcode::G_FPOW:
1289 case TargetOpcode::G_FREM:
1290 case TargetOpcode::G_FCOS:
1291 case TargetOpcode::G_FSIN:
1292 case TargetOpcode::G_FTAN:
1293 case TargetOpcode::G_FACOS:
1294 case TargetOpcode::G_FASIN:
1295 case TargetOpcode::G_FATAN:
1296 case TargetOpcode::G_FATAN2:
1297 case TargetOpcode::G_FCOSH:
1298 case TargetOpcode::G_FSINH:
1299 case TargetOpcode::G_FTANH:
1300 case TargetOpcode::G_FLOG10:
1301 case TargetOpcode::G_FLOG:
1302 case TargetOpcode::G_FLOG2:
1303 case TargetOpcode::G_FEXP:
1304 case TargetOpcode::G_FEXP2:
1305 case TargetOpcode::G_FEXP10:
1306 case TargetOpcode::G_FCEIL:
1307 case TargetOpcode::G_FFLOOR:
1308 case TargetOpcode::G_FMINNUM:
1309 case TargetOpcode::G_FMAXNUM:
1310 case TargetOpcode::G_FSQRT:
1311 case TargetOpcode::G_FRINT:
1312 case TargetOpcode::G_FNEARBYINT:
1313 case TargetOpcode::G_INTRINSIC_TRUNC:
1314 case TargetOpcode::G_INTRINSIC_ROUND:
1315 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1316 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1320 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1328 case TargetOpcode::G_FSINCOS: {
1329 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1333 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1338 case TargetOpcode::G_LROUND:
1339 case TargetOpcode::G_LLROUND:
1340 case TargetOpcode::G_INTRINSIC_LRINT:
1341 case TargetOpcode::G_INTRINSIC_LLRINT: {
1342 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1346 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1348 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1354 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1357 MI.eraseFromParent();
1360 case TargetOpcode::G_FPOWI:
1361 case TargetOpcode::G_FLDEXP: {
1362 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1366 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1368 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1373 {
MI.getOperand(1).getReg(), HLTy, 0},
1374 {
MI.getOperand(2).getReg(), ITy, 1}};
1375 Args[1].Flags[0].setSExt();
1378 Args, LocObserver, &
MI);
1383 case TargetOpcode::G_FPEXT:
1384 case TargetOpcode::G_FPTRUNC: {
1387 if (!FromTy || !ToTy)
1395 case TargetOpcode::G_FCMP: {
1399 MI.eraseFromParent();
1402 case TargetOpcode::G_FPTOSI:
1403 case TargetOpcode::G_FPTOUI: {
1407 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1408 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1416 case TargetOpcode::G_SITOFP:
1417 case TargetOpcode::G_UITOFP: {
1418 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1421 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1423 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1426 LocObserver, TLI, IsSigned);
1431 case TargetOpcode::G_ATOMICRMW_XCHG:
1432 case TargetOpcode::G_ATOMICRMW_ADD:
1433 case TargetOpcode::G_ATOMICRMW_SUB:
1434 case TargetOpcode::G_ATOMICRMW_AND:
1435 case TargetOpcode::G_ATOMICRMW_OR:
1436 case TargetOpcode::G_ATOMICRMW_XOR:
1437 case TargetOpcode::G_ATOMIC_CMPXCHG:
1438 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1444 case TargetOpcode::G_BZERO:
1445 case TargetOpcode::G_MEMCPY:
1446 case TargetOpcode::G_MEMMOVE:
1447 case TargetOpcode::G_MEMSET: {
1452 MI.eraseFromParent();
1455 case TargetOpcode::G_GET_FPENV:
1456 case TargetOpcode::G_GET_FPMODE: {
1462 case TargetOpcode::G_SET_FPENV:
1463 case TargetOpcode::G_SET_FPMODE: {
1469 case TargetOpcode::G_RESET_FPENV:
1470 case TargetOpcode::G_RESET_FPMODE: {
1479 MI.eraseFromParent();
1486 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1489 switch (
MI.getOpcode()) {
1492 case TargetOpcode::G_IMPLICIT_DEF: {
1494 LLT DstTy = MRI.getType(DstReg);
1502 if (SizeOp0 % NarrowSize != 0) {
1503 LLT ImplicitTy = NarrowTy;
1510 MI.eraseFromParent();
1514 int NumParts = SizeOp0 / NarrowSize;
1517 for (
int i = 0; i < NumParts; ++i)
1521 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1523 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1524 MI.eraseFromParent();
1527 case TargetOpcode::G_CONSTANT: {
1528 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1529 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1530 unsigned TotalSize = Ty.getSizeInBits();
1532 int NumParts = TotalSize / NarrowSize;
1535 for (
int I = 0;
I != NumParts; ++
I) {
1536 unsigned Offset =
I * NarrowSize;
1543 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1545 if (LeftoverBits != 0) {
1549 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1553 insertParts(
MI.getOperand(0).getReg(),
1554 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1556 MI.eraseFromParent();
1559 case TargetOpcode::G_SEXT:
1560 case TargetOpcode::G_ZEXT:
1561 case TargetOpcode::G_ANYEXT:
1563 case TargetOpcode::G_TRUNC: {
1567 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1569 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1573 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1574 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1575 MI.eraseFromParent();
1578 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1579 case TargetOpcode::G_FREEZE: {
1583 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1588 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1590 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1592 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1596 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1597 MI.eraseFromParent();
1600 case TargetOpcode::G_ADD:
1601 case TargetOpcode::G_SUB:
1602 case TargetOpcode::G_SADDO:
1603 case TargetOpcode::G_SSUBO:
1604 case TargetOpcode::G_SADDE:
1605 case TargetOpcode::G_SSUBE:
1606 case TargetOpcode::G_UADDO:
1607 case TargetOpcode::G_USUBO:
1608 case TargetOpcode::G_UADDE:
1609 case TargetOpcode::G_USUBE:
1611 case TargetOpcode::G_MUL:
1612 case TargetOpcode::G_UMULH:
1614 case TargetOpcode::G_EXTRACT:
1616 case TargetOpcode::G_INSERT:
1618 case TargetOpcode::G_LOAD: {
1620 Register DstReg = LoadMI.getDstReg();
1621 LLT DstTy = MRI.getType(DstReg);
1625 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1626 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1627 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1629 LoadMI.eraseFromParent();
1635 case TargetOpcode::G_ZEXTLOAD:
1636 case TargetOpcode::G_SEXTLOAD: {
1638 Register DstReg = LoadMI.getDstReg();
1639 Register PtrReg = LoadMI.getPointerReg();
1641 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1642 auto &MMO = LoadMI.getMMO();
1645 if (MemSize == NarrowSize) {
1647 }
else if (MemSize < NarrowSize) {
1648 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1649 }
else if (MemSize > NarrowSize) {
1659 LoadMI.eraseFromParent();
1662 case TargetOpcode::G_STORE: {
1665 Register SrcReg = StoreMI.getValueReg();
1666 LLT SrcTy = MRI.getType(SrcReg);
1667 if (SrcTy.isVector())
1670 int NumParts = SizeOp0 / NarrowSize;
1672 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1673 if (SrcTy.isVector() && LeftoverBits != 0)
1676 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1677 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1679 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1680 StoreMI.eraseFromParent();
1686 case TargetOpcode::G_SELECT:
1688 case TargetOpcode::G_AND:
1689 case TargetOpcode::G_OR:
1690 case TargetOpcode::G_XOR: {
1702 case TargetOpcode::G_SHL:
1703 case TargetOpcode::G_LSHR:
1704 case TargetOpcode::G_ASHR:
1706 case TargetOpcode::G_CTLZ:
1707 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1708 case TargetOpcode::G_CTTZ:
1709 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1710 case TargetOpcode::G_CTPOP:
1712 switch (
MI.getOpcode()) {
1713 case TargetOpcode::G_CTLZ:
1714 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
1716 case TargetOpcode::G_CTTZ:
1717 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
1719 case TargetOpcode::G_CTPOP:
1729 case TargetOpcode::G_INTTOPTR:
1737 case TargetOpcode::G_PTRTOINT:
1745 case TargetOpcode::G_PHI: {
1748 if (SizeOp0 % NarrowSize != 0)
1751 unsigned NumParts = SizeOp0 / NarrowSize;
1755 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1763 for (
unsigned i = 0; i < NumParts; ++i) {
1764 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1766 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1767 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1768 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1771 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1773 MI.eraseFromParent();
1776 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1777 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1781 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1787 case TargetOpcode::G_ICMP: {
1789 LLT SrcTy = MRI.getType(LHS);
1795 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1801 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1802 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1808 LLT ResTy = MRI.getType(Dst);
1813 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1815 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1816 auto LHS = std::get<0>(LHSAndRHS);
1817 auto RHS = std::get<1>(LHSAndRHS);
1818 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1825 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1826 auto LHS = std::get<0>(LHSAndRHS);
1827 auto RHS = std::get<1>(LHSAndRHS);
1828 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1829 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1830 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1831 TargetOpcode::G_ZEXT);
1838 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1839 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1840 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1845 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1849 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1854 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1858 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1861 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1864 LHSPartRegs[
I], RHSPartRegs[
I]);
1865 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1871 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1875 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1880 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1884 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1885 RHSLeftoverRegs[
I]);
1887 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1888 RHSLeftoverRegs[
I]);
1891 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1892 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1898 MI.eraseFromParent();
1901 case TargetOpcode::G_FCMP:
1910 case TargetOpcode::G_SEXT_INREG: {
1914 int64_t SizeInBits =
MI.getOperand(2).getImm();
1923 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
1924 MO1.
setReg(TruncMIB.getReg(0));
1927 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
1939 if (SizeOp0 % NarrowSize != 0)
1941 int NumParts = SizeOp0 / NarrowSize;
1949 for (
int i = 0; i < NumParts; ++i) {
1950 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
1965 for (
int i = 0; i < NumParts; ++i) {
1968 PartialExtensionReg = DstRegs.
back();
1970 assert(PartialExtensionReg &&
1971 "Expected to visit partial extension before full");
1972 if (FullExtensionReg) {
1977 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
1979 FullExtensionReg = DstRegs.
back();
1984 TargetOpcode::G_SEXT_INREG, {NarrowTy},
1987 PartialExtensionReg = DstRegs.
back();
1993 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1994 MI.eraseFromParent();
1997 case TargetOpcode::G_BSWAP:
1998 case TargetOpcode::G_BITREVERSE: {
1999 if (SizeOp0 % NarrowSize != 0)
2004 unsigned NumParts = SizeOp0 / NarrowSize;
2005 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2008 for (
unsigned i = 0; i < NumParts; ++i) {
2009 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2010 {SrcRegs[NumParts - 1 - i]});
2014 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2017 MI.eraseFromParent();
2020 case TargetOpcode::G_PTR_ADD:
2021 case TargetOpcode::G_PTRMASK: {
2029 case TargetOpcode::G_FPTOUI:
2030 case TargetOpcode::G_FPTOSI:
2031 case TargetOpcode::G_FPTOUI_SAT:
2032 case TargetOpcode::G_FPTOSI_SAT:
2034 case TargetOpcode::G_FPEXT:
2041 case TargetOpcode::G_FLDEXP:
2042 case TargetOpcode::G_STRICT_FLDEXP:
2044 case TargetOpcode::G_VSCALE: {
2046 LLT Ty = MRI.getType(Dst);
2050 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2051 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2052 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2055 MI.eraseFromParent();
2062 LLT Ty = MRI.getType(Val);
2068 if (Ty.isPointer()) {
2069 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2071 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2077 if (Ty.isPointerVector())
2078 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2079 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2083 unsigned OpIdx,
unsigned ExtOpcode) {
2085 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2086 MO.
setReg(ExtB.getReg(0));
2092 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2093 MO.
setReg(ExtB.getReg(0));
2097 unsigned OpIdx,
unsigned TruncOpcode) {
2099 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2101 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2106 unsigned OpIdx,
unsigned ExtOpcode) {
2108 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2110 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2119 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2121 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2127 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2137 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2144LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2149 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2150 if (DstTy.isVector())
2153 LLT SrcTy =
MRI.getType(Src1Reg);
2154 const int DstSize = DstTy.getSizeInBits();
2155 const int SrcSize = SrcTy.getSizeInBits();
2157 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2159 unsigned NumOps =
MI.getNumOperands();
2160 unsigned NumSrc =
MI.getNumOperands() - 1;
2161 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2163 if (WideSize >= DstSize) {
2167 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2168 const unsigned Offset = (
I - 1) * PartSize;
2176 MRI.createGenericVirtualRegister(WideTy);
2181 ResultReg = NextResult;
2184 if (WideSize > DstSize)
2186 else if (DstTy.isPointer())
2189 MI.eraseFromParent();
2214 const int GCD = std::gcd(SrcSize, WideSize);
2224 if (GCD == SrcSize) {
2227 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2228 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2234 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2236 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2240 const int PartsPerGCD = WideSize / GCD;
2244 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2246 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2253 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2255 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2256 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2259 MI.eraseFromParent();
2264LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2269 int NumDst =
MI.getNumOperands() - 1;
2270 Register SrcReg =
MI.getOperand(NumDst).getReg();
2271 LLT SrcTy = MRI.getType(SrcReg);
2275 Register Dst0Reg =
MI.getOperand(0).getReg();
2276 LLT DstTy = MRI.getType(Dst0Reg);
2285 dbgs() <<
"Not casting non-integral address space integer\n");
2290 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2298 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2306 for (
int I = 1;
I != NumDst; ++
I) {
2307 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2308 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2312 MI.eraseFromParent();
2323 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2327 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2330 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2348 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2353 if (PartsPerRemerge == 1) {
2356 for (
int I = 0;
I != NumUnmerge; ++
I) {
2357 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2359 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2360 int Idx =
I * PartsPerUnmerge + J;
2362 MIB.addDef(
MI.getOperand(Idx).getReg());
2365 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2369 MIB.addUse(Unmerge.getReg(
I));
2372 SmallVector<Register, 16> Parts;
2373 for (
int J = 0; J != NumUnmerge; ++J)
2374 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2377 for (
int I = 0;
I != NumDst; ++
I) {
2378 for (
int J = 0; J < PartsPerRemerge; ++J) {
2379 const int Idx =
I * PartsPerRemerge + J;
2383 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2384 RemergeParts.
clear();
2388 MI.eraseFromParent();
2393LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2395 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2396 unsigned Offset =
MI.getOperand(2).getImm();
2399 if (SrcTy.
isVector() || DstTy.isVector())
2411 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2415 if (DstTy.isPointer())
2422 MI.eraseFromParent();
2427 LLT ShiftTy = SrcTy;
2436 MI.eraseFromParent();
2467LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2469 if (TypeIdx != 0 || WideTy.
isVector())
2479LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2483 std::optional<Register> CarryIn;
2484 switch (
MI.getOpcode()) {
2487 case TargetOpcode::G_SADDO:
2488 Opcode = TargetOpcode::G_ADD;
2489 ExtOpcode = TargetOpcode::G_SEXT;
2491 case TargetOpcode::G_SSUBO:
2492 Opcode = TargetOpcode::G_SUB;
2493 ExtOpcode = TargetOpcode::G_SEXT;
2495 case TargetOpcode::G_UADDO:
2496 Opcode = TargetOpcode::G_ADD;
2497 ExtOpcode = TargetOpcode::G_ZEXT;
2499 case TargetOpcode::G_USUBO:
2500 Opcode = TargetOpcode::G_SUB;
2501 ExtOpcode = TargetOpcode::G_ZEXT;
2503 case TargetOpcode::G_SADDE:
2504 Opcode = TargetOpcode::G_UADDE;
2505 ExtOpcode = TargetOpcode::G_SEXT;
2506 CarryIn =
MI.getOperand(4).getReg();
2508 case TargetOpcode::G_SSUBE:
2509 Opcode = TargetOpcode::G_USUBE;
2510 ExtOpcode = TargetOpcode::G_SEXT;
2511 CarryIn =
MI.getOperand(4).getReg();
2513 case TargetOpcode::G_UADDE:
2514 Opcode = TargetOpcode::G_UADDE;
2515 ExtOpcode = TargetOpcode::G_ZEXT;
2516 CarryIn =
MI.getOperand(4).getReg();
2518 case TargetOpcode::G_USUBE:
2519 Opcode = TargetOpcode::G_USUBE;
2520 ExtOpcode = TargetOpcode::G_ZEXT;
2521 CarryIn =
MI.getOperand(4).getReg();
2537 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2538 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2542 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2544 .buildInstr(Opcode, {WideTy, CarryOutTy},
2545 {LHSExt, RHSExt, *CarryIn})
2548 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2550 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2551 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2552 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2557 MI.eraseFromParent();
2562LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2564 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2565 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2566 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2567 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2568 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2581 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2588 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2592 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2593 {ShiftL, ShiftR},
MI.getFlags());
2598 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2601 MI.eraseFromParent();
2606LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2615 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2617 LLT SrcTy = MRI.getType(
LHS);
2618 LLT OverflowTy = MRI.getType(OriginalOverflow);
2625 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2626 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2627 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2634 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2636 MachineInstrBuilder Mulo;
2637 if (WideMulCanOverflow)
2638 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2639 {LeftOperand, RightOperand});
2641 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2646 MachineInstrBuilder ExtResult;
2653 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2657 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2660 if (WideMulCanOverflow) {
2668 MI.eraseFromParent();
2674 unsigned Opcode =
MI.getOpcode();
2678 case TargetOpcode::G_ATOMICRMW_XCHG:
2679 case TargetOpcode::G_ATOMICRMW_ADD:
2680 case TargetOpcode::G_ATOMICRMW_SUB:
2681 case TargetOpcode::G_ATOMICRMW_AND:
2682 case TargetOpcode::G_ATOMICRMW_OR:
2683 case TargetOpcode::G_ATOMICRMW_XOR:
2684 case TargetOpcode::G_ATOMICRMW_MIN:
2685 case TargetOpcode::G_ATOMICRMW_MAX:
2686 case TargetOpcode::G_ATOMICRMW_UMIN:
2687 case TargetOpcode::G_ATOMICRMW_UMAX:
2688 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2694 case TargetOpcode::G_ATOMIC_CMPXCHG:
2695 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2702 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2712 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2717 case TargetOpcode::G_EXTRACT:
2718 return widenScalarExtract(
MI, TypeIdx, WideTy);
2719 case TargetOpcode::G_INSERT:
2720 return widenScalarInsert(
MI, TypeIdx, WideTy);
2721 case TargetOpcode::G_MERGE_VALUES:
2722 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2723 case TargetOpcode::G_UNMERGE_VALUES:
2724 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2725 case TargetOpcode::G_SADDO:
2726 case TargetOpcode::G_SSUBO:
2727 case TargetOpcode::G_UADDO:
2728 case TargetOpcode::G_USUBO:
2729 case TargetOpcode::G_SADDE:
2730 case TargetOpcode::G_SSUBE:
2731 case TargetOpcode::G_UADDE:
2732 case TargetOpcode::G_USUBE:
2733 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2734 case TargetOpcode::G_UMULO:
2735 case TargetOpcode::G_SMULO:
2736 return widenScalarMulo(
MI, TypeIdx, WideTy);
2737 case TargetOpcode::G_SADDSAT:
2738 case TargetOpcode::G_SSUBSAT:
2739 case TargetOpcode::G_SSHLSAT:
2740 case TargetOpcode::G_UADDSAT:
2741 case TargetOpcode::G_USUBSAT:
2742 case TargetOpcode::G_USHLSAT:
2743 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2744 case TargetOpcode::G_CTTZ:
2745 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
2746 case TargetOpcode::G_CTLZ:
2747 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
2748 case TargetOpcode::G_CTPOP: {
2759 unsigned ExtOpc = Opcode == TargetOpcode::G_CTTZ ||
2760 Opcode == TargetOpcode::G_CTTZ_ZERO_UNDEF
2761 ? TargetOpcode::G_ANYEXT
2762 : TargetOpcode::G_ZEXT;
2763 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2764 LLT CurTy = MRI.getType(SrcReg);
2765 unsigned NewOpc = Opcode;
2766 if (NewOpc == TargetOpcode::G_CTTZ) {
2773 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2775 NewOpc = TargetOpcode::G_CTTZ_ZERO_UNDEF;
2780 if (Opcode == TargetOpcode::G_CTLZ_ZERO_UNDEF) {
2790 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2792 if (Opcode == TargetOpcode::G_CTLZ) {
2795 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff));
2798 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2799 MI.eraseFromParent();
2802 case TargetOpcode::G_BSWAP: {
2806 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2807 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2808 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2811 MI.getOperand(0).setReg(DstExt);
2815 LLT Ty = MRI.getType(DstReg);
2817 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2818 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2824 case TargetOpcode::G_BITREVERSE: {
2828 LLT Ty = MRI.getType(DstReg);
2831 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2833 MI.getOperand(0).setReg(DstExt);
2836 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2837 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2842 case TargetOpcode::G_FREEZE:
2843 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2850 case TargetOpcode::G_ABS:
2857 case TargetOpcode::G_ADD:
2858 case TargetOpcode::G_AND:
2859 case TargetOpcode::G_MUL:
2860 case TargetOpcode::G_OR:
2861 case TargetOpcode::G_XOR:
2862 case TargetOpcode::G_SUB:
2863 case TargetOpcode::G_SHUFFLE_VECTOR:
2874 case TargetOpcode::G_SBFX:
2875 case TargetOpcode::G_UBFX:
2889 case TargetOpcode::G_SHL:
2905 case TargetOpcode::G_ROTR:
2906 case TargetOpcode::G_ROTL:
2915 case TargetOpcode::G_SDIV:
2916 case TargetOpcode::G_SREM:
2917 case TargetOpcode::G_SMIN:
2918 case TargetOpcode::G_SMAX:
2919 case TargetOpcode::G_ABDS:
2927 case TargetOpcode::G_SDIVREM:
2936 case TargetOpcode::G_ASHR:
2937 case TargetOpcode::G_LSHR:
2941 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
2942 : TargetOpcode::G_ZEXT;
2955 case TargetOpcode::G_UDIV:
2956 case TargetOpcode::G_UREM:
2957 case TargetOpcode::G_ABDU:
2964 case TargetOpcode::G_UDIVREM:
2972 case TargetOpcode::G_UMIN:
2973 case TargetOpcode::G_UMAX: {
2974 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
2976 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
2980 ? TargetOpcode::G_SEXT
2981 : TargetOpcode::G_ZEXT;
2991 case TargetOpcode::G_SELECT:
3001 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3008 case TargetOpcode::G_FPTOSI:
3009 case TargetOpcode::G_FPTOUI:
3010 case TargetOpcode::G_INTRINSIC_LRINT:
3011 case TargetOpcode::G_INTRINSIC_LLRINT:
3012 case TargetOpcode::G_IS_FPCLASS:
3022 case TargetOpcode::G_SITOFP:
3032 case TargetOpcode::G_UITOFP:
3042 case TargetOpcode::G_FPTOSI_SAT:
3043 case TargetOpcode::G_FPTOUI_SAT:
3048 LLT Ty = MRI.getType(OldDst);
3049 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3051 MI.getOperand(0).setReg(ExtReg);
3052 uint64_t ShortBits = Ty.getScalarSizeInBits();
3055 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3066 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3067 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3075 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3083 case TargetOpcode::G_LOAD:
3084 case TargetOpcode::G_SEXTLOAD:
3085 case TargetOpcode::G_ZEXTLOAD:
3091 case TargetOpcode::G_STORE: {
3095 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3096 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3097 if (!Ty.isScalar()) {
3105 MI.setMemRefs(MF, {NewMMO});
3112 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3113 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3119 case TargetOpcode::G_CONSTANT: {
3122 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3123 MRI.getType(
MI.getOperand(0).getReg()));
3124 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3125 ExtOpc == TargetOpcode::G_ANYEXT) &&
3128 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3132 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3138 case TargetOpcode::G_FCONSTANT: {
3144 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3146 MI.eraseFromParent();
3149 case TargetOpcode::G_IMPLICIT_DEF: {
3155 case TargetOpcode::G_BRCOND:
3161 case TargetOpcode::G_FCMP:
3172 case TargetOpcode::G_ICMP:
3177 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3181 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3182 unsigned ExtOpcode =
3186 ? TargetOpcode::G_SEXT
3187 : TargetOpcode::G_ZEXT;
3194 case TargetOpcode::G_PTR_ADD:
3195 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3201 case TargetOpcode::G_PHI: {
3202 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3205 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3217 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3220 LLT VecTy = MRI.getType(VecReg);
3225 TargetOpcode::G_ANYEXT);
3240 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3256 LLT VecTy = MRI.getType(VecReg);
3276 case TargetOpcode::G_FADD:
3277 case TargetOpcode::G_FMUL:
3278 case TargetOpcode::G_FSUB:
3279 case TargetOpcode::G_FMA:
3280 case TargetOpcode::G_FMAD:
3281 case TargetOpcode::G_FNEG:
3282 case TargetOpcode::G_FABS:
3283 case TargetOpcode::G_FCANONICALIZE:
3284 case TargetOpcode::G_FMINNUM:
3285 case TargetOpcode::G_FMAXNUM:
3286 case TargetOpcode::G_FMINNUM_IEEE:
3287 case TargetOpcode::G_FMAXNUM_IEEE:
3288 case TargetOpcode::G_FMINIMUM:
3289 case TargetOpcode::G_FMAXIMUM:
3290 case TargetOpcode::G_FMINIMUMNUM:
3291 case TargetOpcode::G_FMAXIMUMNUM:
3292 case TargetOpcode::G_FDIV:
3293 case TargetOpcode::G_FREM:
3294 case TargetOpcode::G_FCEIL:
3295 case TargetOpcode::G_FFLOOR:
3296 case TargetOpcode::G_FCOS:
3297 case TargetOpcode::G_FSIN:
3298 case TargetOpcode::G_FTAN:
3299 case TargetOpcode::G_FACOS:
3300 case TargetOpcode::G_FASIN:
3301 case TargetOpcode::G_FATAN:
3302 case TargetOpcode::G_FATAN2:
3303 case TargetOpcode::G_FCOSH:
3304 case TargetOpcode::G_FSINH:
3305 case TargetOpcode::G_FTANH:
3306 case TargetOpcode::G_FLOG10:
3307 case TargetOpcode::G_FLOG:
3308 case TargetOpcode::G_FLOG2:
3309 case TargetOpcode::G_FRINT:
3310 case TargetOpcode::G_FNEARBYINT:
3311 case TargetOpcode::G_FSQRT:
3312 case TargetOpcode::G_FEXP:
3313 case TargetOpcode::G_FEXP2:
3314 case TargetOpcode::G_FEXP10:
3315 case TargetOpcode::G_FPOW:
3316 case TargetOpcode::G_INTRINSIC_TRUNC:
3317 case TargetOpcode::G_INTRINSIC_ROUND:
3318 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3322 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3328 case TargetOpcode::G_FPOWI:
3329 case TargetOpcode::G_FLDEXP:
3330 case TargetOpcode::G_STRICT_FLDEXP: {
3332 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3353 case TargetOpcode::G_FFREXP: {
3366 case TargetOpcode::G_INTTOPTR:
3374 case TargetOpcode::G_PTRTOINT:
3382 case TargetOpcode::G_BUILD_VECTOR: {
3386 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3392 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3400 case TargetOpcode::G_SEXT_INREG:
3409 case TargetOpcode::G_PTRMASK: {
3417 case TargetOpcode::G_VECREDUCE_ADD: {
3426 case TargetOpcode::G_VECREDUCE_FADD:
3427 case TargetOpcode::G_VECREDUCE_FMUL:
3428 case TargetOpcode::G_VECREDUCE_FMIN:
3429 case TargetOpcode::G_VECREDUCE_FMAX:
3430 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3431 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3436 LLT VecTy = MRI.getType(VecReg);
3445 case TargetOpcode::G_VSCALE: {
3452 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3457 case TargetOpcode::G_SPLAT_VECTOR: {
3466 case TargetOpcode::G_INSERT_SUBVECTOR: {
3474 LLT SubVecTy = MRI.getType(SubVec);
3478 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3479 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3480 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3484 auto SplatZero =
MIRBuilder.buildSplatVector(
3489 MI.eraseFromParent();
3498 auto Unmerge =
B.buildUnmerge(Ty, Src);
3499 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3508 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3510 LLT DstLLT =
MRI.getType(DstReg);
3522 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3531 MI.eraseFromParent();
3542 MI.eraseFromParent();
3549 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3550 if (SrcTy.isVector()) {
3554 if (DstTy.isVector()) {
3555 int NumDstElt = DstTy.getNumElements();
3556 int NumSrcElt = SrcTy.getNumElements();
3559 LLT DstCastTy = DstEltTy;
3560 LLT SrcPartTy = SrcEltTy;
3564 if (NumSrcElt < NumDstElt) {
3574 SrcPartTy = SrcEltTy;
3575 }
else if (NumSrcElt > NumDstElt) {
3586 DstCastTy = DstEltTy;
3591 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3595 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3596 MI.eraseFromParent();
3600 if (DstTy.isVector()) {
3603 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3604 MI.eraseFromParent();
3620 unsigned NewEltSize,
3621 unsigned OldEltSize) {
3622 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3623 LLT IdxTy =
B.getMRI()->getType(Idx);
3626 auto OffsetMask =
B.buildConstant(
3628 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3629 return B.buildShl(IdxTy, OffsetIdx,
3630 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3645 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3649 unsigned OldNumElts = SrcVecTy.getNumElements();
3656 if (NewNumElts > OldNumElts) {
3667 if (NewNumElts % OldNumElts != 0)
3671 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3675 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3678 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3680 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3681 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3682 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3683 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3684 NewOps[
I] = Elt.getReg(0);
3687 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3689 MI.eraseFromParent();
3693 if (NewNumElts < OldNumElts) {
3694 if (NewEltSize % OldEltSize != 0)
3716 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3717 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3720 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3724 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3725 ScaledIdx).getReg(0);
3733 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3735 MI.eraseFromParent();
3749 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3750 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3751 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3752 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3755 auto EltMask =
B.buildConstant(
3759 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3760 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3763 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3767 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3781 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3782 MI.getFirst4RegLLTs();
3794 if (NewNumElts < OldNumElts) {
3795 if (NewEltSize % OldEltSize != 0)
3804 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3805 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3808 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3812 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3813 ScaledIdx).getReg(0);
3823 InsertedElt =
MIRBuilder.buildInsertVectorElement(
3824 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
3828 MI.eraseFromParent();
3858 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
3862 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
3863 return UnableToLegalize;
3868 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
3870 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
3879 MI.eraseFromParent();
3897 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
3898 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
3908 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
3909 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
3911 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
3912 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
3914 MI.eraseFromParent();
3944 LLT DstTy = MRI.getType(Dst);
3945 LLT SrcTy = MRI.getType(Src);
3951 if (DstTy == CastTy)
3959 if (CastEltSize < DstEltSize)
3962 auto AdjustAmt = CastEltSize / DstEltSize;
3963 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
3964 SrcTyMinElts % AdjustAmt != 0)
3969 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
3970 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
3973 ES->eraseFromParent();
4008 LLT DstTy = MRI.getType(Dst);
4009 LLT BigVecTy = MRI.getType(BigVec);
4010 LLT SubVecTy = MRI.getType(SubVec);
4012 if (DstTy == CastTy)
4027 if (CastEltSize < DstEltSize)
4030 auto AdjustAmt = CastEltSize / DstEltSize;
4031 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4032 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4038 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4039 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4041 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4044 ES->eraseFromParent();
4052 LLT DstTy = MRI.getType(DstReg);
4060 if (MemSizeInBits != MemStoreSizeInBits) {
4077 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4081 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4082 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4084 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4087 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4089 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4092 if (DstTy != LoadTy)
4100 if (
MIRBuilder.getDataLayout().isBigEndian())
4118 uint64_t LargeSplitSize, SmallSplitSize;
4123 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4130 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4133 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4144 if (Alignment.
value() * 8 > MemSizeInBits &&
4149 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4166 LLT PtrTy = MRI.getType(PtrReg);
4169 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4173 LargeSplitSize / 8);
4174 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4175 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4177 SmallPtr, *SmallMMO);
4179 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4180 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4182 if (AnyExtTy == DstTy)
4183 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4185 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4189 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4209 LLT SrcTy = MRI.getType(SrcReg);
4217 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4223 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4225 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4229 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4233 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4248 uint64_t LargeSplitSize, SmallSplitSize;
4255 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4258 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4267 if (SrcTy.isPointer()) {
4269 SrcReg =
MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
4272 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4275 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4276 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4279 LLT PtrTy = MRI.getType(PtrReg);
4282 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4288 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4289 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4298 LLT SrcTy = MRI.getType(SrcReg);
4304 assert(SrcTy.isVector() &&
"Expect a vector store type");
4311 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4315 auto Elt =
MIRBuilder.buildExtractVectorElement(
4316 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4317 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4318 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4324 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4325 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4329 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4340 switch (
MI.getOpcode()) {
4341 case TargetOpcode::G_LOAD: {
4359 case TargetOpcode::G_STORE: {
4375 case TargetOpcode::G_SELECT: {
4379 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4381 dbgs() <<
"bitcast action not implemented for vector select\n");
4392 case TargetOpcode::G_AND:
4393 case TargetOpcode::G_OR:
4394 case TargetOpcode::G_XOR: {
4402 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4404 case TargetOpcode::G_INSERT_VECTOR_ELT:
4406 case TargetOpcode::G_CONCAT_VECTORS:
4408 case TargetOpcode::G_SHUFFLE_VECTOR:
4410 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4412 case TargetOpcode::G_INSERT_SUBVECTOR:
4420void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4430 switch(
MI.getOpcode()) {
4433 case TargetOpcode::G_FCONSTANT:
4435 case TargetOpcode::G_BITCAST:
4437 case TargetOpcode::G_SREM:
4438 case TargetOpcode::G_UREM: {
4439 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4441 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4442 {MI.getOperand(1), MI.getOperand(2)});
4444 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4446 MI.eraseFromParent();
4449 case TargetOpcode::G_SADDO:
4450 case TargetOpcode::G_SSUBO:
4452 case TargetOpcode::G_UMULH:
4453 case TargetOpcode::G_SMULH:
4455 case TargetOpcode::G_SMULO:
4456 case TargetOpcode::G_UMULO: {
4459 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4460 LLT Ty = MRI.getType(Res);
4462 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4463 ? TargetOpcode::G_SMULH
4464 : TargetOpcode::G_UMULH;
4468 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4469 MI.removeOperand(1);
4472 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4480 if (Opcode == TargetOpcode::G_SMULH) {
4481 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4482 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4489 case TargetOpcode::G_FNEG: {
4490 auto [Res, SubByReg] =
MI.getFirst2Regs();
4491 LLT Ty = MRI.getType(Res);
4495 MIRBuilder.buildXor(Res, SubByReg, SignMask);
4496 MI.eraseFromParent();
4499 case TargetOpcode::G_FSUB:
4500 case TargetOpcode::G_STRICT_FSUB: {
4501 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4502 LLT Ty = MRI.getType(Res);
4507 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4508 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4512 MI.eraseFromParent();
4515 case TargetOpcode::G_FMAD:
4517 case TargetOpcode::G_FFLOOR:
4519 case TargetOpcode::G_LROUND:
4520 case TargetOpcode::G_LLROUND: {
4523 LLT SrcTy = MRI.getType(SrcReg);
4524 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4527 MI.eraseFromParent();
4530 case TargetOpcode::G_INTRINSIC_ROUND:
4532 case TargetOpcode::G_FRINT: {
4535 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4538 case TargetOpcode::G_INTRINSIC_LRINT:
4539 case TargetOpcode::G_INTRINSIC_LLRINT: {
4542 LLT SrcTy = MRI.getType(SrcReg);
4544 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4546 MI.eraseFromParent();
4549 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4550 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4551 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4552 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4553 **
MI.memoperands_begin());
4555 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4556 MI.eraseFromParent();
4559 case TargetOpcode::G_LOAD:
4560 case TargetOpcode::G_SEXTLOAD:
4561 case TargetOpcode::G_ZEXTLOAD:
4563 case TargetOpcode::G_STORE:
4565 case TargetOpcode::G_CTLZ_ZERO_UNDEF:
4566 case TargetOpcode::G_CTTZ_ZERO_UNDEF:
4567 case TargetOpcode::G_CTLZ:
4568 case TargetOpcode::G_CTTZ:
4569 case TargetOpcode::G_CTPOP:
4572 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4574 Register NewRes = MRI.cloneVirtualRegister(Res);
4581 MI.eraseFromParent();
4585 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4586 const LLT CondTy = MRI.getType(CarryOut);
4587 const LLT Ty = MRI.getType(Res);
4589 Register NewRes = MRI.cloneVirtualRegister(Res);
4592 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4598 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4599 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4606 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4611 MI.eraseFromParent();
4615 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4620 MI.eraseFromParent();
4624 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4625 const LLT CondTy = MRI.getType(BorrowOut);
4626 const LLT Ty = MRI.getType(Res);
4629 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4635 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4636 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4643 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4644 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4646 MI.eraseFromParent();
4679 case G_MERGE_VALUES:
4681 case G_UNMERGE_VALUES:
4683 case TargetOpcode::G_SEXT_INREG: {
4684 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4685 int64_t SizeInBits =
MI.getOperand(2).getImm();
4687 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4688 LLT DstTy = MRI.getType(DstReg);
4689 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4692 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4693 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4694 MI.eraseFromParent();
4697 case G_EXTRACT_VECTOR_ELT:
4698 case G_INSERT_VECTOR_ELT:
4700 case G_SHUFFLE_VECTOR:
4702 case G_VECTOR_COMPRESS:
4704 case G_DYN_STACKALLOC:
4708 case G_STACKRESTORE:
4718 case G_READ_REGISTER:
4719 case G_WRITE_REGISTER:
4726 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4727 if (LI.isLegalOrCustom({G_UMIN, Ty}))
4733 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4738 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
4749 bool IsSigned =
MI.getOpcode() == G_ABDS;
4750 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4751 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
4752 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
4776 case G_MEMCPY_INLINE:
4777 return lowerMemcpyInline(
MI);
4788 case G_ATOMICRMW_SUB: {
4789 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
4790 const LLT ValTy = MRI.getType(Val);
4794 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
4795 MI.eraseFromParent();
4818 unsigned AddrSpace =
DL.getAllocaAddrSpace();
4822 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
4828 Align StackTypeAlign =
4835 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
4836 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
4841 LLT IdxTy =
B.getMRI()->getType(IdxReg);
4853 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
4856 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
4867 "Converting bits to bytes lost precision");
4873 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
4874 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
4876 if (IdxTy != MRI.getType(Index))
4877 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
4882 LLT PtrTy = MRI.getType(VecPtr);
4883 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
4891 std::initializer_list<unsigned> NonVecOpIndices) {
4892 if (
MI.getNumMemOperands() != 0)
4895 LLT VecTy =
MRI.getType(
MI.getReg(0));
4909 if (!Ty.isVector()) {
4915 if (Ty.getNumElements() != NumElts)
4930 assert(Ty.isVector() &&
"Expected vector type");
4933 int NumParts, NumLeftover;
4934 std::tie(NumParts, NumLeftover) =
4937 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
4938 for (
int i = 0; i < NumParts; ++i) {
4943 assert(NumLeftover == 1 &&
"expected exactly one leftover");
4952 for (
unsigned i = 0; i <
N; ++i) {
4954 Ops.push_back(
Op.getReg());
4955 else if (
Op.isImm())
4956 Ops.push_back(
Op.getImm());
4957 else if (
Op.isPredicate())
4979 std::initializer_list<unsigned> NonVecOpIndices) {
4981 "Non-compatible opcode or not specified non-vector operands");
4982 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
4984 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
4985 unsigned NumDefs =
MI.getNumDefs();
4993 for (
unsigned i = 0; i < NumDefs; ++i) {
4994 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5002 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5003 ++UseIdx, ++UseNo) {
5006 MI.getOperand(UseIdx));
5015 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5019 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5021 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5022 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5025 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5026 Uses.push_back(InputOpsPieces[InputNo][i]);
5029 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5030 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5035 for (
unsigned i = 0; i < NumDefs; ++i)
5036 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5038 for (
unsigned i = 0; i < NumDefs; ++i)
5039 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5042 MI.eraseFromParent();
5049 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5051 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5052 unsigned NumDefs =
MI.getNumDefs();
5056 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5061 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5062 UseIdx += 2, ++UseNo) {
5070 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5072 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5073 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5075 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5078 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5079 Phi.addUse(InputOpsPieces[j][i]);
5080 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5090 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5092 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5095 MI.eraseFromParent();
5103 const int NumDst =
MI.getNumOperands() - 1;
5104 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5105 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5106 LLT SrcTy = MRI.getType(SrcReg);
5108 if (TypeIdx != 1 || NarrowTy == DstTy)
5115 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5118 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5132 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5133 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5134 const int PartsPerUnmerge = NumDst / NumUnmerge;
5136 for (
int I = 0;
I != NumUnmerge; ++
I) {
5137 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5139 for (
int J = 0; J != PartsPerUnmerge; ++J)
5140 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5141 MIB.addUse(Unmerge.getReg(
I));
5144 MI.eraseFromParent();
5151 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5155 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5157 if (NarrowTy == SrcTy)
5165 assert(SrcTy.isVector() &&
"Expected vector types");
5167 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5181 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5182 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5183 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5189 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5190 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5191 ++i,
Offset += NumNarrowTyElts) {
5194 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5197 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5198 MI.eraseFromParent();
5202 assert(TypeIdx == 0 &&
"Bad type index");
5203 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5218 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5219 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5221 for (
unsigned i = 0; i < NumParts; ++i) {
5223 for (
unsigned j = 0; j < NumElts; ++j)
5224 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5226 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5229 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5230 MI.eraseFromParent();
5238 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5240 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5242 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5244 InsertVal =
MI.getOperand(2).getReg();
5246 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5247 LLT VecTy = MRI.getType(SrcVec);
5253 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5257 MI.eraseFromParent();
5266 SplitPieces[IdxVal] = InsertVal;
5267 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5269 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5273 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5276 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5277 TargetOpcode::G_ANYEXT);
5281 LLT IdxTy = MRI.getType(Idx);
5282 int64_t PartIdx = IdxVal / NewNumElts;
5284 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5287 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5290 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5291 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5292 VecParts[PartIdx] = InsertPart.getReg(0);
5296 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5298 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5302 MI.eraseFromParent();
5322 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5334 LLT ValTy = MRI.getType(ValReg);
5343 int NumLeftover = -1;
5349 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5351 NumParts = NarrowRegs.
size();
5352 NumLeftover = NarrowLeftoverRegs.
size();
5359 LLT PtrTy = MRI.getType(AddrReg);
5362 unsigned TotalSize = ValTy.getSizeInBits();
5369 auto MMO = LdStMI.
getMMO();
5371 unsigned NumParts,
unsigned Offset) ->
unsigned {
5374 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5376 unsigned ByteOffset =
Offset / 8;
5379 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5386 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5387 ValRegs.push_back(Dst);
5388 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5390 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5399 unsigned HandledOffset =
5400 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5404 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5407 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5408 LeftoverTy, NarrowLeftoverRegs);
5422 switch (
MI.getOpcode()) {
5423 case G_IMPLICIT_DEF:
5439 case G_FCANONICALIZE:
5456 case G_INTRINSIC_LRINT:
5457 case G_INTRINSIC_LLRINT:
5458 case G_INTRINSIC_ROUND:
5459 case G_INTRINSIC_ROUNDEVEN:
5462 case G_INTRINSIC_TRUNC:
5489 case G_FMINNUM_IEEE:
5490 case G_FMAXNUM_IEEE:
5512 case G_CTLZ_ZERO_UNDEF:
5514 case G_CTTZ_ZERO_UNDEF:
5530 case G_ADDRSPACE_CAST:
5543 case G_STRICT_FLDEXP:
5552 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5557 case G_UNMERGE_VALUES:
5559 case G_BUILD_VECTOR:
5560 assert(TypeIdx == 0 &&
"not a vector type index");
5562 case G_CONCAT_VECTORS:
5566 case G_EXTRACT_VECTOR_ELT:
5567 case G_INSERT_VECTOR_ELT:
5576 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5577 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5579 case G_SHUFFLE_VECTOR:
5585 case G_INTRINSIC_FPTRUNC_ROUND:
5595 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5596 "Not a bitcast operation");
5601 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5603 unsigned NewElemCount =
5606 if (NewElemCount == 1) {
5609 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5615 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5624 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5625 MI.eraseFromParent();
5631 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5635 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5636 MI.getFirst3RegLLTs();
5639 if (DstTy != Src1Ty)
5641 if (DstTy != Src2Ty)
5656 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
5672 unsigned InputUsed[2] = {-1U, -1U};
5673 unsigned FirstMaskIdx =
High * NewElts;
5674 bool UseBuildVector =
false;
5675 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5677 int Idx = Mask[FirstMaskIdx + MaskOffset];
5682 if (
Input >= std::size(Inputs)) {
5689 Idx -=
Input * NewElts;
5693 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
5694 if (InputUsed[OpNo] ==
Input) {
5697 }
else if (InputUsed[OpNo] == -1U) {
5699 InputUsed[OpNo] =
Input;
5704 if (OpNo >= std::size(InputUsed)) {
5707 UseBuildVector =
true;
5712 Ops.push_back(Idx + OpNo * NewElts);
5715 if (UseBuildVector) {
5720 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
5722 int Idx = Mask[FirstMaskIdx + MaskOffset];
5727 if (
Input >= std::size(Inputs)) {
5734 Idx -=
Input * NewElts;
5738 .buildExtractVectorElement(
5739 EltTy, Inputs[
Input],
5745 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
5746 }
else if (InputUsed[0] == -1U) {
5748 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
5750 Register Op0 = Inputs[InputUsed[0]];
5754 : Inputs[InputUsed[1]];
5756 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
5763 MI.eraseFromParent();
5776 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
5782 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
5785 const unsigned NumParts =
5787 : SrcTy.getNumElements();
5791 if (DstTy != NarrowTy)
5797 unsigned NumPartsLeft = NumParts;
5798 while (NumPartsLeft > 1) {
5799 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
5802 .buildInstr(ScalarOpc, {NarrowTy},
5803 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
5806 SplitSrcs = PartialResults;
5807 PartialResults.
clear();
5808 NumPartsLeft = SplitSrcs.
size();
5812 MI.eraseFromParent();
5817 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
5818 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
5821 MI.eraseFromParent();
5825 for (
unsigned Part = 0; Part < NumParts; ++Part) {
5827 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
5835 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
5838 Register Acc = PartialReductions[0];
5839 for (
unsigned Part = 1; Part < NumParts; ++Part) {
5840 if (Part == NumParts - 1) {
5842 {Acc, PartialReductions[Part]});
5845 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
5849 MI.eraseFromParent();
5855 unsigned int TypeIdx,
5857 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
5858 MI.getFirst3RegLLTs();
5859 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
5863 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
5864 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
5865 "Unexpected vecreduce opcode");
5866 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
5867 ? TargetOpcode::G_FADD
5868 : TargetOpcode::G_FMUL;
5871 unsigned NumParts = SrcTy.getNumElements();
5874 for (
unsigned i = 0; i < NumParts; i++)
5875 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
5879 MI.eraseFromParent();
5886 unsigned ScalarOpc) {
5894 while (SplitSrcs.
size() > 1) {
5896 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
5904 SplitSrcs = std::move(PartialRdxs);
5908 MI.getOperand(1).setReg(SplitSrcs[0]);
5915 const LLT HalfTy,
const LLT AmtTy) {
5917 Register InL = MRI.createGenericVirtualRegister(HalfTy);
5918 Register InH = MRI.createGenericVirtualRegister(HalfTy);
5922 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
5923 MI.eraseFromParent();
5929 unsigned VTBits = 2 * NVTBits;
5932 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
5933 if (Amt.
ugt(VTBits)) {
5935 }
else if (Amt.
ugt(NVTBits)) {
5938 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5939 }
else if (Amt == NVTBits) {
5947 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5950 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
5951 if (Amt.
ugt(VTBits)) {
5953 }
else if (Amt.
ugt(NVTBits)) {
5955 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5957 }
else if (Amt == NVTBits) {
5961 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
5963 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
5965 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5971 if (Amt.
ugt(VTBits)) {
5973 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5974 }
else if (Amt.
ugt(NVTBits)) {
5976 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
5978 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5979 }
else if (Amt == NVTBits) {
5982 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
5984 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
5986 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
5988 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
5995 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
5996 MI.eraseFromParent();
6012 LLT DstTy = MRI.getType(DstReg);
6017 LLT ShiftAmtTy = MRI.getType(Amt);
6019 if (DstEltSize % 2 != 0)
6035 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6046 const unsigned NewBitSize = DstEltSize / 2;
6058 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6060 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6061 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6064 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6065 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6067 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6072 switch (
MI.getOpcode()) {
6073 case TargetOpcode::G_SHL: {
6075 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6077 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6078 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6079 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6082 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6083 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6085 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6087 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6089 ResultRegs[0] =
Lo.getReg(0);
6090 ResultRegs[1] =
Hi.getReg(0);
6093 case TargetOpcode::G_LSHR:
6094 case TargetOpcode::G_ASHR: {
6096 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6098 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6099 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6100 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6104 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6107 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6108 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6110 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6114 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6116 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6118 ResultRegs[0] =
Lo.getReg(0);
6119 ResultRegs[1] =
Hi.getReg(0);
6126 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6127 MI.eraseFromParent();
6136 LLT TargetTy,
LLT ShiftAmtTy) {
6139 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6141 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6142 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6143 const bool NeedsInterWordShift = ShiftBits != 0;
6146 case TargetOpcode::G_SHL: {
6149 if (PartIdx < ShiftWords)
6152 unsigned SrcIdx = PartIdx - ShiftWords;
6153 if (!NeedsInterWordShift)
6154 return SrcParts[SrcIdx];
6159 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6163 return Hi.getReg(0);
6166 case TargetOpcode::G_LSHR: {
6167 unsigned SrcIdx = PartIdx + ShiftWords;
6168 if (SrcIdx >= NumParts)
6170 if (!NeedsInterWordShift)
6171 return SrcParts[SrcIdx];
6175 if (SrcIdx + 1 < NumParts) {
6176 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6180 return Lo.getReg(0);
6183 case TargetOpcode::G_ASHR: {
6185 unsigned SrcIdx = PartIdx + ShiftWords;
6186 if (SrcIdx >= NumParts)
6188 if (!NeedsInterWordShift)
6189 return SrcParts[SrcIdx];
6194 (SrcIdx == NumParts - 1)
6198 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6220 unsigned MainOpcode =
6221 (Opcode == TargetOpcode::G_ASHR) ? TargetOpcode::G_LSHR : Opcode;
6225 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6234 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6235 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6237 auto IsZeroBitShift =
6245 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6246 : TargetOpcode::G_SHL;
6249 auto TargetBitsConst =
6251 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6256 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6261 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6263 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6267 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6280 LLT DstTy = MRI.getType(DstReg);
6284 const unsigned NumParts = DstBits / TargetBits;
6286 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6296 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6297 MI.eraseFromParent();
6302 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6303 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6309 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6313 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6316 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6317 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6321 for (
unsigned I = 0;
I < NumParts; ++
I)
6323 Params, TargetTy, ShiftAmtTy);
6325 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6326 MI.eraseFromParent();
6335 LLT DstTy = MRI.getType(DstReg);
6336 LLT ShiftAmtTy = MRI.getType(AmtReg);
6340 const unsigned NumParts = DstBits / TargetBits;
6342 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6359 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6371 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6372 auto TargetBitsLog2Const =
6373 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6374 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6377 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6379 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6387 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6388 auto TargetBitsMinusOneConst =
6389 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6391 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6392 TargetBitsMinusOneConst)
6395 FillValue = ZeroReg;
6403 for (
unsigned I = 0;
I < NumParts; ++
I) {
6405 Register InBoundsResult = FillValue;
6415 for (
unsigned K = 0; K < NumParts; ++K) {
6416 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6418 WordShift, WordShiftKConst);
6430 switch (
MI.getOpcode()) {
6431 case TargetOpcode::G_SHL:
6432 MainSrcIdx = (int)
I - (
int)K;
6433 CarrySrcIdx = MainSrcIdx - 1;
6435 case TargetOpcode::G_LSHR:
6436 case TargetOpcode::G_ASHR:
6437 MainSrcIdx = (int)
I + (
int)K;
6438 CarrySrcIdx = MainSrcIdx + 1;
6446 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6447 Register MainOp = SrcParts[MainSrcIdx];
6451 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6452 CarryOp = SrcParts[CarrySrcIdx];
6453 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6454 CarrySrcIdx >= (
int)NumParts)
6455 CarryOp = FillValue;
6461 ResultForK = FillValue;
6467 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6474 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6478 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6479 MI.eraseFromParent();
6486 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6489 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6504 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6509 "getNeutralElementForVecReduce called with invalid opcode!");
6510 case TargetOpcode::G_VECREDUCE_ADD:
6511 case TargetOpcode::G_VECREDUCE_OR:
6512 case TargetOpcode::G_VECREDUCE_XOR:
6513 case TargetOpcode::G_VECREDUCE_UMAX:
6515 case TargetOpcode::G_VECREDUCE_MUL:
6517 case TargetOpcode::G_VECREDUCE_AND:
6518 case TargetOpcode::G_VECREDUCE_UMIN:
6521 case TargetOpcode::G_VECREDUCE_SMAX:
6524 case TargetOpcode::G_VECREDUCE_SMIN:
6527 case TargetOpcode::G_VECREDUCE_FADD:
6529 case TargetOpcode::G_VECREDUCE_FMUL:
6531 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6532 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6533 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6534 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6542 unsigned Opc =
MI.getOpcode();
6544 case TargetOpcode::G_IMPLICIT_DEF:
6545 case TargetOpcode::G_LOAD: {
6553 case TargetOpcode::G_STORE:
6560 case TargetOpcode::G_AND:
6561 case TargetOpcode::G_OR:
6562 case TargetOpcode::G_XOR:
6563 case TargetOpcode::G_ADD:
6564 case TargetOpcode::G_SUB:
6565 case TargetOpcode::G_MUL:
6566 case TargetOpcode::G_FADD:
6567 case TargetOpcode::G_FSUB:
6568 case TargetOpcode::G_FMUL:
6569 case TargetOpcode::G_FDIV:
6570 case TargetOpcode::G_FCOPYSIGN:
6571 case TargetOpcode::G_UADDSAT:
6572 case TargetOpcode::G_USUBSAT:
6573 case TargetOpcode::G_SADDSAT:
6574 case TargetOpcode::G_SSUBSAT:
6575 case TargetOpcode::G_SMIN:
6576 case TargetOpcode::G_SMAX:
6577 case TargetOpcode::G_UMIN:
6578 case TargetOpcode::G_UMAX:
6579 case TargetOpcode::G_FMINNUM:
6580 case TargetOpcode::G_FMAXNUM:
6581 case TargetOpcode::G_FMINNUM_IEEE:
6582 case TargetOpcode::G_FMAXNUM_IEEE:
6583 case TargetOpcode::G_FMINIMUM:
6584 case TargetOpcode::G_FMAXIMUM:
6585 case TargetOpcode::G_FMINIMUMNUM:
6586 case TargetOpcode::G_FMAXIMUMNUM:
6587 case TargetOpcode::G_STRICT_FADD:
6588 case TargetOpcode::G_STRICT_FSUB:
6589 case TargetOpcode::G_STRICT_FMUL:
6590 case TargetOpcode::G_SHL:
6591 case TargetOpcode::G_ASHR:
6592 case TargetOpcode::G_LSHR: {
6600 case TargetOpcode::G_FMA:
6601 case TargetOpcode::G_STRICT_FMA:
6602 case TargetOpcode::G_FSHR:
6603 case TargetOpcode::G_FSHL: {
6612 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6613 case TargetOpcode::G_EXTRACT:
6620 case TargetOpcode::G_INSERT:
6621 case TargetOpcode::G_INSERT_VECTOR_ELT:
6622 case TargetOpcode::G_FREEZE:
6623 case TargetOpcode::G_FNEG:
6624 case TargetOpcode::G_FABS:
6625 case TargetOpcode::G_FSQRT:
6626 case TargetOpcode::G_FCEIL:
6627 case TargetOpcode::G_FFLOOR:
6628 case TargetOpcode::G_FNEARBYINT:
6629 case TargetOpcode::G_FRINT:
6630 case TargetOpcode::G_INTRINSIC_ROUND:
6631 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6632 case TargetOpcode::G_INTRINSIC_TRUNC:
6633 case TargetOpcode::G_BITREVERSE:
6634 case TargetOpcode::G_BSWAP:
6635 case TargetOpcode::G_FCANONICALIZE:
6636 case TargetOpcode::G_SEXT_INREG:
6637 case TargetOpcode::G_ABS:
6638 case TargetOpcode::G_CTLZ:
6639 case TargetOpcode::G_CTPOP:
6647 case TargetOpcode::G_SELECT: {
6648 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
6650 if (!CondTy.isScalar() ||
6656 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
6658 MI.getOperand(1).setReg(ShufSplat.getReg(0));
6663 if (CondTy.isVector())
6673 case TargetOpcode::G_UNMERGE_VALUES:
6675 case TargetOpcode::G_PHI:
6677 case TargetOpcode::G_SHUFFLE_VECTOR:
6679 case TargetOpcode::G_BUILD_VECTOR: {
6681 for (
auto Op :
MI.uses()) {
6689 MIRBuilder.buildDeleteTrailingVectorElements(
6690 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
6691 MI.eraseFromParent();
6694 case TargetOpcode::G_SEXT:
6695 case TargetOpcode::G_ZEXT:
6696 case TargetOpcode::G_ANYEXT:
6697 case TargetOpcode::G_TRUNC:
6698 case TargetOpcode::G_FPTRUNC:
6699 case TargetOpcode::G_FPEXT:
6700 case TargetOpcode::G_FPTOSI:
6701 case TargetOpcode::G_FPTOUI:
6702 case TargetOpcode::G_FPTOSI_SAT:
6703 case TargetOpcode::G_FPTOUI_SAT:
6704 case TargetOpcode::G_SITOFP:
6705 case TargetOpcode::G_UITOFP: {
6713 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
6717 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6725 case TargetOpcode::G_ICMP:
6726 case TargetOpcode::G_FCMP: {
6735 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
6740 case TargetOpcode::G_BITCAST: {
6744 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
6745 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
6761 case TargetOpcode::G_VECREDUCE_FADD:
6762 case TargetOpcode::G_VECREDUCE_FMUL:
6763 case TargetOpcode::G_VECREDUCE_ADD:
6764 case TargetOpcode::G_VECREDUCE_MUL:
6765 case TargetOpcode::G_VECREDUCE_AND:
6766 case TargetOpcode::G_VECREDUCE_OR:
6767 case TargetOpcode::G_VECREDUCE_XOR:
6768 case TargetOpcode::G_VECREDUCE_SMAX:
6769 case TargetOpcode::G_VECREDUCE_SMIN:
6770 case TargetOpcode::G_VECREDUCE_UMAX:
6771 case TargetOpcode::G_VECREDUCE_UMIN: {
6772 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
6774 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
6775 auto NeutralElement = getNeutralElementForVecReduce(
6781 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
6782 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
6783 NeutralElement, Idx);
6787 MO.
setReg(NewVec.getReg(0));
6799 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6801 unsigned MaskNumElts = Mask.size();
6802 unsigned SrcNumElts = SrcTy.getNumElements();
6805 if (MaskNumElts == SrcNumElts)
6808 if (MaskNumElts < SrcNumElts) {
6816 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6817 MI.getOperand(1).getReg(),
6818 MI.getOperand(2).getReg(), NewMask);
6819 MI.eraseFromParent();
6824 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
6825 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
6833 MOps1[0] =
MI.getOperand(1).getReg();
6834 MOps2[0] =
MI.getOperand(2).getReg();
6836 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
6837 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
6841 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
6843 if (Idx >=
static_cast<int>(SrcNumElts))
6844 Idx += PaddedMaskNumElts - SrcNumElts;
6849 if (MaskNumElts != PaddedMaskNumElts) {
6851 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
6854 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
6856 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
6861 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
6864 MI.eraseFromParent();
6870 unsigned int TypeIdx,
LLT MoreTy) {
6871 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
6873 unsigned NumElts = DstTy.getNumElements();
6876 if (DstTy.isVector() && Src1Ty.isVector() &&
6877 DstTy.getNumElements() != Src1Ty.getNumElements()) {
6885 if (DstTy != Src1Ty || DstTy != Src2Ty)
6893 for (
unsigned I = 0;
I != NumElts; ++
I) {
6895 if (Idx <
static_cast<int>(NumElts))
6898 NewMask[
I] = Idx - NumElts + WidenNumElts;
6902 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
6903 MI.getOperand(1).getReg(),
6904 MI.getOperand(2).getReg(), NewMask);
6905 MI.eraseFromParent();
6914 unsigned SrcParts = Src1Regs.
size();
6915 unsigned DstParts = DstRegs.
size();
6917 unsigned DstIdx = 0;
6919 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
6920 DstRegs[DstIdx] = FactorSum;
6925 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
6927 for (
unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
6928 i <= std::min(DstIdx, SrcParts - 1); ++i) {
6930 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
6934 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
6935 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
6937 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
6947 if (DstIdx != DstParts - 1) {
6948 MachineInstrBuilder Uaddo =
6949 B.buildUAddo(NarrowTy,
LLT::scalar(1), Factors[0], Factors[1]);
6950 FactorSum = Uaddo.
getReg(0);
6951 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
6952 for (
unsigned i = 2; i < Factors.
size(); ++i) {
6953 MachineInstrBuilder Uaddo =
6954 B.buildUAddo(NarrowTy,
LLT::scalar(1), FactorSum, Factors[i]);
6955 FactorSum = Uaddo.
getReg(0);
6956 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
6957 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
6961 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
6962 for (
unsigned i = 2; i < Factors.
size(); ++i)
6963 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
6966 CarrySumPrevDstIdx = CarrySum;
6967 DstRegs[DstIdx] = FactorSum;
6979 LLT DstType = MRI.getType(DstReg);
6981 if (DstType.isVector())
6984 unsigned Opcode =
MI.getOpcode();
6985 unsigned OpO, OpE, OpF;
6987 case TargetOpcode::G_SADDO:
6988 case TargetOpcode::G_SADDE:
6989 case TargetOpcode::G_UADDO:
6990 case TargetOpcode::G_UADDE:
6991 case TargetOpcode::G_ADD:
6992 OpO = TargetOpcode::G_UADDO;
6993 OpE = TargetOpcode::G_UADDE;
6994 OpF = TargetOpcode::G_UADDE;
6995 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
6996 OpF = TargetOpcode::G_SADDE;
6998 case TargetOpcode::G_SSUBO:
6999 case TargetOpcode::G_SSUBE:
7000 case TargetOpcode::G_USUBO:
7001 case TargetOpcode::G_USUBE:
7002 case TargetOpcode::G_SUB:
7003 OpO = TargetOpcode::G_USUBO;
7004 OpE = TargetOpcode::G_USUBE;
7005 OpF = TargetOpcode::G_USUBE;
7006 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7007 OpF = TargetOpcode::G_SSUBE;
7014 unsigned NumDefs =
MI.getNumExplicitDefs();
7015 Register Src1 =
MI.getOperand(NumDefs).getReg();
7016 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7019 CarryDst =
MI.getOperand(1).getReg();
7020 if (
MI.getNumOperands() == NumDefs + 3)
7021 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7023 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7024 LLT LeftoverTy, DummyTy;
7026 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7031 int NarrowParts = Src1Regs.
size();
7032 Src1Regs.
append(Src1Left);
7033 Src2Regs.
append(Src2Left);
7036 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7038 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7041 if (i == e - 1 && CarryDst)
7042 CarryOut = CarryDst;
7044 CarryOut = MRI.createGenericVirtualRegister(
LLT::scalar(1));
7047 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7048 {Src1Regs[i], Src2Regs[i]});
7049 }
else if (i == e - 1) {
7050 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7051 {Src1Regs[i], Src2Regs[i], CarryIn});
7053 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7054 {Src1Regs[i], Src2Regs[i], CarryIn});
7060 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7061 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7062 ArrayRef(DstRegs).drop_front(NarrowParts));
7064 MI.eraseFromParent();
7070 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7072 LLT Ty = MRI.getType(DstReg);
7076 unsigned Size = Ty.getSizeInBits();
7078 if (
Size % NarrowSize != 0)
7081 unsigned NumParts =
Size / NarrowSize;
7082 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7083 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7089 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7093 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7094 MI.eraseFromParent();
7104 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7107 LLT SrcTy = MRI.getType(Src);
7118 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7131 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7134 if (SizeOp1 % NarrowSize != 0)
7136 int NumParts = SizeOp1 / NarrowSize;
7139 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7143 uint64_t OpStart =
MI.getOperand(2).getImm();
7144 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7145 for (
int i = 0; i < NumParts; ++i) {
7146 unsigned SrcStart = i * NarrowSize;
7148 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7151 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7159 int64_t ExtractOffset;
7161 if (OpStart < SrcStart) {
7163 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7165 ExtractOffset = OpStart - SrcStart;
7166 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7170 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7172 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7173 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7180 if (MRI.getType(DstReg).isVector())
7181 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7182 else if (DstRegs.
size() > 1)
7183 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7186 MI.eraseFromParent();
7198 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7200 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7203 SrcRegs.
append(LeftoverRegs);
7207 uint64_t OpStart =
MI.getOperand(3).getImm();
7208 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7209 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7210 unsigned DstStart =
I * NarrowSize;
7212 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7220 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7222 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7226 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7234 int64_t ExtractOffset, InsertOffset;
7236 if (OpStart < DstStart) {
7238 ExtractOffset = DstStart - OpStart;
7239 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7241 InsertOffset = OpStart - DstStart;
7244 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7248 if (ExtractOffset != 0 || SegSize != OpSize) {
7250 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7251 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7254 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7255 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7263 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7266 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7268 MI.eraseFromParent();
7276 LLT DstTy = MRI.getType(DstReg);
7278 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7284 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7285 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7289 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7290 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7293 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7294 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7295 {Src0Regs[I], Src1Regs[I]});
7299 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7302 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7303 DstLeftoverRegs.
push_back(Inst.getReg(0));
7306 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7307 LeftoverTy, DstLeftoverRegs);
7309 MI.eraseFromParent();
7319 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7321 LLT DstTy = MRI.getType(DstReg);
7326 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7327 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7328 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7330 MI.eraseFromParent();
7340 Register CondReg =
MI.getOperand(1).getReg();
7341 LLT CondTy = MRI.getType(CondReg);
7346 LLT DstTy = MRI.getType(DstReg);
7352 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7353 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7357 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7358 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7361 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7363 CondReg, Src1Regs[
I], Src2Regs[
I]);
7367 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7369 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7373 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7374 LeftoverTy, DstLeftoverRegs);
7376 MI.eraseFromParent();
7386 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7389 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7390 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF;
7393 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7395 auto C_0 =
B.buildConstant(NarrowTy, 0);
7397 UnmergeSrc.getReg(1), C_0);
7398 auto LoCTLZ = IsUndef ?
7399 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) :
7400 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7401 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7402 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7403 auto HiCTLZ =
B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1));
7404 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7406 MI.eraseFromParent();
7419 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7422 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7423 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF;
7426 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7428 auto C_0 =
B.buildConstant(NarrowTy, 0);
7430 UnmergeSrc.getReg(0), C_0);
7431 auto HiCTTZ = IsUndef ?
7432 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) :
7433 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7434 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7435 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7436 auto LoCTTZ =
B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0));
7437 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7439 MI.eraseFromParent();
7452 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7455 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7456 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7458 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7459 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7460 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7462 MI.eraseFromParent();
7477 LLT ExpTy = MRI.getType(ExpReg);
7482 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7483 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7484 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7485 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7487 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7489 MI.getOperand(2).setReg(Trunc.getReg(0));
7496 unsigned Opc =
MI.getOpcode();
7499 auto QAction = LI.getAction(Q).Action;
7505 case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
7508 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7512 case TargetOpcode::G_CTLZ: {
7513 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7514 unsigned Len = SrcTy.getSizeInBits();
7516 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7518 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg);
7519 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7522 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7523 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7524 MI.eraseFromParent();
7540 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7541 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7544 Op = MIBOp.getReg(0);
7549 MI.eraseFromParent();
7552 case TargetOpcode::G_CTTZ_ZERO_UNDEF: {
7555 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7559 case TargetOpcode::G_CTTZ: {
7560 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7562 unsigned Len = SrcTy.getSizeInBits();
7563 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) {
7566 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg);
7567 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7570 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7571 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7572 MI.eraseFromParent();
7579 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7580 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7582 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7583 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7584 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7585 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7588 MI.eraseFromParent();
7592 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
7593 MI.getOperand(1).setReg(MIBTmp.getReg(0));
7597 case TargetOpcode::G_CTPOP: {
7599 LLT Ty = MRI.getType(SrcReg);
7600 unsigned Size = Ty.getSizeInBits();
7608 auto C_1 =
B.buildConstant(Ty, 1);
7609 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
7611 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
7612 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
7613 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
7617 auto C_2 =
B.buildConstant(Ty, 2);
7618 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
7620 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
7621 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
7622 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
7623 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
7630 auto C_4 =
B.buildConstant(Ty, 4);
7631 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
7632 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
7634 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
7635 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
7637 assert(
Size<=128 &&
"Scalar size is too large for CTPOP lower algorithm");
7643 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
7645 auto IsMulSupported = [
this](
const LLT Ty) {
7646 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
7649 if (IsMulSupported(Ty)) {
7650 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
7651 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7653 auto ResTmp = B8Count;
7654 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
7655 auto ShiftC =
B.buildConstant(Ty, Shift);
7656 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
7657 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
7659 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
7661 MI.eraseFromParent();
7682 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7683 LLT Ty = MRI.getType(Dst);
7684 LLT ShTy = MRI.getType(Z);
7691 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7692 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7697 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
7698 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
7702 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7715 MI.eraseFromParent();
7721 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
7722 LLT Ty = MRI.getType(Dst);
7723 LLT ShTy = MRI.getType(Z);
7726 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7736 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7737 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7738 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
7739 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
7740 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
7744 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
7747 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
7750 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
7752 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
7753 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
7754 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
7757 auto One =
MIRBuilder.buildConstant(ShTy, 1);
7759 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
7761 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
7764 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
7765 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
7770 MI.eraseFromParent();
7781 LLT Ty = MRI.getType(Dst);
7782 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
7784 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
7785 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
7788 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
7789 return lowerFunnelShiftAsShifts(
MI);
7793 if (Result == UnableToLegalize)
7794 return lowerFunnelShiftAsShifts(
MI);
7799 auto [Dst, Src] =
MI.getFirst2Regs();
7800 LLT DstTy = MRI.getType(Dst);
7801 LLT SrcTy = MRI.getType(Src);
7805 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
7813 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
7817 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
7821 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
7826 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7827 {UnmergeSrc.getReg(0)});
7828 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
7829 {UnmergeSrc.getReg(1)});
7832 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
7834 MI.eraseFromParent();
7851 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
7855 LLT DstTy = MRI.getType(DstReg);
7856 LLT SrcTy = MRI.getType(SrcReg);
7864 SrcTy.getElementCount().divideCoefficientBy(2));
7877 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
7889 MI.eraseFromParent();
7898 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7899 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
7900 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7901 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7902 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
7903 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
7904 MI.eraseFromParent();
7909 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
7911 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
7912 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
7917 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
7918 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
7920 return lowerRotateWithReverseRotate(
MI);
7923 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7924 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
7925 bool IsFShLegal =
false;
7926 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
7927 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
7931 MI.eraseFromParent();
7936 return buildFunnelShift(FShOpc, Dst, Src, Amt);
7939 return buildFunnelShift(RevFsh, Dst, Src, Amt);
7944 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
7945 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
7946 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
7952 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
7953 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
7955 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
7961 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
7962 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
7964 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
7966 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
7970 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal);
7971 MI.eraseFromParent();
7979 auto [Dst, Src] =
MI.getFirst2Regs();
7984 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8012 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8025 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8029 MI.eraseFromParent();
8037 auto [Dst, Src] =
MI.getFirst2Regs();
8042 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8055 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8057 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8062 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8064 MI.eraseFromParent();
8072 auto [Dst, Src] =
MI.getFirst2Regs();
8076 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8087 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8088 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8090 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8097 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8098 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8099 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8101 MI.eraseFromParent();
8111 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8117 MI.eraseFromParent();
8122 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8125 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8126 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8127 MIRBuilder.buildSelect(Dst, Src, True, False);
8128 MI.eraseFromParent();
8132 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8152 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8159 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8160 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8161 MIRBuilder.buildSelect(Dst, Src, True, False);
8162 MI.eraseFromParent();
8166 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8189 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8190 MI.eraseFromParent();
8198 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8202 if (SrcTy !=
S64 && SrcTy !=
S32)
8204 if (DstTy !=
S32 && DstTy !=
S64)
8231 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8233 MI.eraseFromParent();
8238 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8243 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8250 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8252 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8253 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8255 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8256 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8258 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8260 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8261 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8262 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8265 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8266 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8267 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8269 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8272 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8277 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8278 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8284 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8286 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8287 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8289 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8294 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8295 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8297 MI.eraseFromParent();
8303 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8305 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8306 unsigned SatWidth = DstTy.getScalarSizeInBits();
8310 APInt MinInt, MaxInt;
8333 if (AreExactFloatBounds) {
8335 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8337 SrcTy.changeElementSize(1), Src, MaxC);
8338 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8340 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8350 MI.eraseFromParent();
8355 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8357 DstTy.changeElementSize(1), Src, Src);
8360 MI.eraseFromParent();
8367 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8376 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8387 MI.eraseFromParent();
8393 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8395 DstTy.changeElementSize(1), Src, Src);
8397 MI.eraseFromParent();
8407 auto [Dst, Src] =
MI.getFirst2Regs();
8409 MRI.getType(Src).getScalarType() ==
LLT::scalar(64));
8411 if (MRI.getType(Src).isVector())
8415 unsigned Flags =
MI.getFlags();
8418 MI.eraseFromParent();
8422 const unsigned ExpMask = 0x7ff;
8423 const unsigned ExpBiasf64 = 1023;
8424 const unsigned ExpBiasf16 = 15;
8453 auto SelectCC =
MIRBuilder.buildSelect(
S32, CmpM_NE0, Bits0x200, Zero);
8513 MI.eraseFromParent();
8519 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8523 if (DstTy.getScalarType() ==
S16 && SrcTy.getScalarType() ==
S64)
8530 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8531 LLT Ty = MRI.getType(Dst);
8533 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
8534 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
8535 MI.eraseFromParent();
8541 case TargetOpcode::G_SMIN:
8543 case TargetOpcode::G_SMAX:
8545 case TargetOpcode::G_UMIN:
8547 case TargetOpcode::G_UMAX:
8555 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8560 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
8561 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
8563 MI.eraseFromParent();
8572 LLT DstTy = MRI.getType(Dst);
8573 LLT SrcTy = MRI.getType(Cmp->getReg(1));
8583 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
8584 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
8586 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
8589 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
8590 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
8593 auto One =
MIRBuilder.buildConstant(DstTy, 1);
8594 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
8596 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
8597 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
8603 unsigned BoolExtOp =
8605 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
8606 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
8610 MI.eraseFromParent();
8616 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
8617 const int Src0Size = Src0Ty.getScalarSizeInBits();
8618 const int Src1Size = Src1Ty.getScalarSizeInBits();
8623 auto NotSignBitMask =
MIRBuilder.buildConstant(
8628 if (Src0Ty == Src1Ty) {
8629 And1 =
MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
8630 }
else if (Src0Size > Src1Size) {
8631 auto ShiftAmt =
MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
8632 auto Zext =
MIRBuilder.buildZExt(Src0Ty, Src1);
8633 auto Shift =
MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
8634 And1 =
MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
8636 auto ShiftAmt =
MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
8637 auto Shift =
MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
8638 auto Trunc =
MIRBuilder.buildTrunc(Src0Ty, Shift);
8639 And1 =
MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
8645 unsigned Flags =
MI.getFlags();
8652 MI.eraseFromParent();
8663 switch (
MI.getOpcode()) {
8664 case TargetOpcode::G_FMINNUM:
8665 NewOp = TargetOpcode::G_FMINNUM_IEEE;
8667 case TargetOpcode::G_FMINIMUMNUM:
8668 NewOp = TargetOpcode::G_FMINNUM;
8670 case TargetOpcode::G_FMAXNUM:
8671 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
8673 case TargetOpcode::G_FMAXIMUMNUM:
8674 NewOp = TargetOpcode::G_FMAXNUM;
8680 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
8681 LLT Ty = MRI.getType(Dst);
8691 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
8694 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
8699 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
8700 MI.eraseFromParent();
8707 LLT Ty = MRI.getType(DstReg);
8708 unsigned Flags =
MI.getFlags();
8713 MI.eraseFromParent();
8719 auto [DstReg,
X] =
MI.getFirst2Regs();
8720 const unsigned Flags =
MI.getFlags();
8721 const LLT Ty = MRI.getType(DstReg);
8733 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
8735 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
8740 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
8741 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8742 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
8743 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
8745 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
8747 MI.eraseFromParent();
8752 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
8753 unsigned Flags =
MI.getFlags();
8754 LLT Ty = MRI.getType(DstReg);
8761 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
8762 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
8765 SrcReg, Zero, Flags);
8767 SrcReg, Trunc, Flags);
8771 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
8772 MI.eraseFromParent();
8778 const unsigned NumOps =
MI.getNumOperands();
8779 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
8780 unsigned PartSize = Src0Ty.getSizeInBits();
8785 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
8786 const unsigned Offset = (
I - 1) * PartSize;
8789 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
8792 MRI.createGenericVirtualRegister(WideTy);
8795 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
8796 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
8797 ResultReg = NextResult;
8800 if (DstTy.isPointer()) {
8801 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
8802 DstTy.getAddressSpace())) {
8810 MI.eraseFromParent();
8816 const unsigned NumDst =
MI.getNumOperands() - 1;
8817 Register SrcReg =
MI.getOperand(NumDst).getReg();
8818 Register Dst0Reg =
MI.getOperand(0).getReg();
8819 LLT DstTy = MRI.getType(Dst0Reg);
8828 LLT IntTy = MRI.getType(SrcReg);
8833 unsigned Offset = DstSize;
8834 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
8836 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
8840 MI.eraseFromParent();
8859 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
8860 InsertVal =
MI.getOperand(2).getReg();
8862 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
8864 LLT VecTy = MRI.getType(SrcVec);
8874 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
8875 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
8877 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
8880 MI.eraseFromParent();
8885 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
8896 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
8903 int64_t
Offset = IdxVal * EltBytes;
8914 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
8917 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
8919 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
8922 MI.eraseFromParent();
8928 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
8929 MI.getFirst3RegLLTs();
8937 for (
int Idx : Mask) {
8939 if (!Undef.isValid())
8940 Undef =
MIRBuilder.buildUndef(EltTy).getReg(0);
8945 if (Src0Ty.isScalar()) {
8946 BuildVec.
push_back(Idx == 0 ? Src0Reg : Src1Reg);
8948 int NumElts = Src0Ty.getNumElements();
8949 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
8950 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
8951 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
8952 auto Extract =
MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK);
8957 if (DstTy.isVector())
8958 MIRBuilder.buildBuildVector(DstReg, BuildVec);
8961 MI.eraseFromParent();
8967 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
8968 MI.getFirst4RegLLTs();
8970 if (VecTy.isScalableVector())
8986 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
8989 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
8992 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
8995 std::optional<APInt> PassthruSplatVal =
8998 if (PassthruSplatVal.has_value()) {
9000 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9001 }
else if (HasPassthru) {
9002 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9003 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9009 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9013 unsigned NumElmts = VecTy.getNumElements();
9014 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9016 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9019 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9022 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9027 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9029 if (HasPassthru &&
I == NumElmts - 1) {
9032 auto AllLanesSelected =
MIRBuilder.buildICmp(
9034 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9035 {OutPos, EndOfVector});
9039 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9041 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9046 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9048 MI.eraseFromParent();
9059 SPTmp =
MIRBuilder.buildCast(IntPtrTy, SPTmp);
9065 if (Alignment >
Align(1)) {
9068 auto AlignCst =
MIRBuilder.buildConstant(IntPtrTy, AlignMask);
9077 const auto &MF = *
MI.getMF();
9083 Register AllocSize =
MI.getOperand(1).getReg();
9086 LLT PtrTy = MRI.getType(Dst);
9087 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9094 MI.eraseFromParent();
9100 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9105 MI.eraseFromParent();
9111 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9116 MI.eraseFromParent();
9122 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9123 unsigned Offset =
MI.getOperand(2).getImm();
9126 if (SrcTy.isVector()) {
9127 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9128 unsigned DstSize = DstTy.getSizeInBits();
9130 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9131 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9133 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9137 for (
unsigned Idx =
Offset / SrcEltSize;
9138 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9139 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9141 if (SubVectorElts.
size() == 1)
9142 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9144 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9146 MI.eraseFromParent();
9151 if (DstTy.isScalar() &&
9152 (SrcTy.isScalar() ||
9153 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9154 LLT SrcIntTy = SrcTy;
9155 if (!SrcTy.isScalar()) {
9157 SrcReg =
MIRBuilder.buildBitcast(SrcIntTy, SrcReg).getReg(0);
9164 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9168 MI.eraseFromParent();
9176 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9179 LLT DstTy = MRI.getType(Src);
9180 LLT InsertTy = MRI.getType(InsertSrc);
9188 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9190 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9194 for (; Idx <
Offset / EltSize; ++Idx) {
9195 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9200 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9201 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9203 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9212 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9215 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9216 MI.eraseFromParent();
9230 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9234 LLT IntDstTy = DstTy;
9238 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
9243 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
9249 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
9255 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
9256 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
9257 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
9260 MI.eraseFromParent();
9266 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
9267 MI.getFirst4RegLLTs();
9268 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
9271 LLT BoolTy = Dst1Ty;
9273 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
9290 auto ResultLowerThanLHS =
9295 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS);
9298 MI.eraseFromParent();
9305 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9306 LLT Ty = MRI.getType(Res);
9310 switch (
MI.getOpcode()) {
9313 case TargetOpcode::G_UADDSAT:
9316 BaseOp = TargetOpcode::G_ADD;
9318 case TargetOpcode::G_SADDSAT:
9321 BaseOp = TargetOpcode::G_ADD;
9323 case TargetOpcode::G_USUBSAT:
9326 BaseOp = TargetOpcode::G_SUB;
9328 case TargetOpcode::G_SSUBSAT:
9331 BaseOp = TargetOpcode::G_SUB;
9346 uint64_t NumBits = Ty.getScalarSizeInBits();
9357 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
9365 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
9370 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
9371 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
9374 MI.eraseFromParent();
9380 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9381 LLT Ty = MRI.getType(Res);
9385 unsigned OverflowOp;
9386 switch (
MI.getOpcode()) {
9389 case TargetOpcode::G_UADDSAT:
9392 OverflowOp = TargetOpcode::G_UADDO;
9394 case TargetOpcode::G_SADDSAT:
9397 OverflowOp = TargetOpcode::G_SADDO;
9399 case TargetOpcode::G_USUBSAT:
9402 OverflowOp = TargetOpcode::G_USUBO;
9404 case TargetOpcode::G_SSUBSAT:
9407 OverflowOp = TargetOpcode::G_SSUBO;
9412 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
9413 Register Tmp = OverflowRes.getReg(0);
9414 Register Ov = OverflowRes.getReg(1);
9423 uint64_t NumBits = Ty.getScalarSizeInBits();
9424 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
9425 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
9428 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
9436 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
9440 MI.eraseFromParent();
9446 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
9447 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
9448 "Expected shlsat opcode!");
9449 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
9450 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
9451 LLT Ty = MRI.getType(Res);
9455 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
9456 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
9465 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
9470 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
9472 MI.eraseFromParent();
9477 auto [Dst, Src] =
MI.getFirst2Regs();
9478 const LLT Ty = MRI.getType(Src);
9479 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
9480 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
9483 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
9484 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
9485 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9486 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
9489 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
9491 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8));
9492 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
9493 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
9495 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
9496 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
9497 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
9499 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
9500 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
9501 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
9503 Res.getInstr()->getOperand(0).setReg(Dst);
9505 MI.eraseFromParent();
9512 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
9515 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
9516 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
9517 return B.buildOr(Dst,
LHS,
RHS);
9522 auto [Dst, Src] =
MI.getFirst2Regs();
9523 const LLT SrcTy = MRI.getType(Src);
9524 unsigned Size = SrcTy.getScalarSizeInBits();
9525 unsigned VSize = SrcTy.getSizeInBits();
9528 if (SrcTy.isVector() && (VSize % 8 == 0) &&
9529 (LI.isLegal({TargetOpcode::G_BITREVERSE,
9530 {LLT::fixed_vector(VSize / 8, 8),
9531 LLT::fixed_vector(VSize / 8, 8)}}))) {
9536 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
9537 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
9538 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
9542 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
9565 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
9569 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
9572 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
9576 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
9580 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
9585 MI.eraseFromParent();
9593 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
9594 int NameOpIdx = IsRead ? 1 : 0;
9595 int ValRegIndex = IsRead ? 0 : 1;
9597 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
9598 const LLT Ty = MRI.getType(ValReg);
9600 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
9607 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
9608 Fn,
MI.getDebugLoc()));
9612 MI.eraseFromParent();
9621 MI.eraseFromParent();
9627 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
9628 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
9630 LLT OrigTy = MRI.getType(Result);
9634 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
9635 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
9637 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
9639 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
9640 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
9643 MI.eraseFromParent();
9649 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9654 MI.eraseFromParent();
9659 MI.eraseFromParent();
9666 unsigned BitSize = SrcTy.getScalarSizeInBits();
9670 if (SrcTy.isVector())
9671 IntTy =
LLT::vector(SrcTy.getElementCount(), IntTy);
9672 auto AsInt =
MIRBuilder.buildCopy(IntTy, SrcReg);
9678 APInt ExpMask = Inf;
9684 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
9685 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
9686 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
9687 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
9688 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
9690 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
9694 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
9696 LLT DstTyCopy = DstTy;
9698 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
9726 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
9729 Mask &= ~PartialCheck;
9738 else if (PartialCheck ==
fcZero)
9750 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
9751 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
9754 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
9756 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
9757 appendToRes(SubnormalRes);
9764 else if (PartialCheck ==
fcInf)
9769 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
9776 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
9777 if (PartialCheck ==
fcNan) {
9781 }
else if (PartialCheck ==
fcQNan) {
9791 Abs, InfWithQnanBitC);
9792 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
9799 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
9801 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
9802 APInt MaxExpMinusOne = ExpMask - ExpLSB;
9805 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
9807 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
9810 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
9811 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
9813 appendToRes(NormalRes);
9817 MI.eraseFromParent();
9823 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
9824 MI.getFirst4RegLLTs();
9826 bool IsEltPtr = DstTy.isPointerOrPointerVector();
9830 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
9831 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
9835 if (MaskTy.isScalar()) {
9843 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
9847 MIRBuilder.buildSExtOrTrunc(DstTy.getScalarType(), MaskElt).getReg(0);
9849 if (DstTy.isVector()) {
9851 auto ShufSplat =
MIRBuilder.buildShuffleSplat(DstTy, MaskElt);
9852 MaskReg = ShufSplat.getReg(0);
9857 }
else if (!DstTy.isVector()) {
9862 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
9866 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
9867 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
9868 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
9875 MI.eraseFromParent();
9881 unsigned Opcode =
MI.getOpcode();
9884 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
9885 : TargetOpcode::G_UDIV,
9886 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9888 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
9889 : TargetOpcode::G_UREM,
9890 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
9891 MI.eraseFromParent();
9901 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
9905 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
9908 MI.eraseFromParent();
9919 LLT Ty = MRI.getType(SrcReg);
9923 MI.eraseFromParent();
9930 Register DestReg =
MI.getOperand(0).getReg();
9932 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
9936 MI.eraseFromParent();
9942 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
9943 MI.getOpcode() == TargetOpcode::G_ABDU) &&
9944 "Expected G_ABDS or G_ABDU instruction");
9946 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
9947 LLT Ty = MRI.getType(LHS);
9957 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
9959 MI.eraseFromParent();
9965 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
9966 MI.getOpcode() == TargetOpcode::G_ABDU) &&
9967 "Expected G_ABDS or G_ABDU instruction");
9969 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
9970 LLT Ty = MRI.getType(LHS);
9975 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
9976 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
9977 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
9979 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
9980 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
9984 MI.eraseFromParent();
9992 LLT Ty = MRI.getType(DstReg);
10000 MI.eraseFromParent();
10006 Register SrcReg =
MI.getOperand(1).getReg();
10007 LLT SrcTy = MRI.getType(SrcReg);
10008 LLT DstTy = MRI.getType(SrcReg);
10011 if (SrcTy.isScalar()) {
10016 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10027 Register ListPtr =
MI.getOperand(1).getReg();
10028 LLT PtrTy = MRI.getType(ListPtr);
10035 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10037 const Align A(
MI.getOperand(2).getImm());
10039 if (
A > TLI.getMinStackArgumentAlignment()) {
10041 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10042 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10043 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10044 VAList = AndDst.getReg(0);
10051 LLT LLTTy = MRI.getType(Dst);
10054 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10055 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10060 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10062 Align EltAlignment =
DL.getABITypeAlign(Ty);
10065 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10067 MI.eraseFromParent();
10082 unsigned Limit,
const MemOp &
Op,
10083 unsigned DstAS,
unsigned SrcAS,
10084 const AttributeList &FuncAttributes,
10086 if (
Op.isMemcpyWithFixedDstAlign() &&
Op.getSrcAlign() <
Op.getDstAlign())
10096 if (
Op.isFixedDstAlign())
10097 while (
Op.getDstAlign() < Ty.getSizeInBytes() &&
10100 assert(Ty.getSizeInBits() > 0 &&
"Could not find valid type");
10104 unsigned NumMemOps = 0;
10107 unsigned TySize = Ty.getSizeInBytes();
10108 while (TySize >
Size) {
10117 assert(NewTySize > 0 &&
"Could not find appropriate type");
10124 if (NumMemOps &&
Op.allowOverlap() && NewTySize <
Size &&
10126 VT, DstAS,
Op.isFixedDstAlign() ?
Op.getDstAlign() :
Align(1),
10132 TySize = NewTySize;
10136 if (++NumMemOps > Limit)
10139 MemOps.push_back(Ty);
10149 unsigned NumBits = Ty.getScalarSizeInBits();
10151 if (!Ty.isVector() && ValVRegAndVal) {
10152 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10160 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
10181 uint64_t KnownLen,
Align Alignment,
10183 auto &MF = *
MI.getParent()->getParent();
10188 assert(KnownLen != 0 &&
"Have a zero length memset length!");
10190 bool DstAlignCanChange =
false;
10194 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10196 DstAlignCanChange =
true;
10198 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
10199 std::vector<LLT> MemOps;
10201 const auto &DstMMO = **
MI.memoperands_begin();
10202 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10205 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
10216 if (DstAlignCanChange) {
10219 Align NewAlign =
DL.getABITypeAlign(IRTy);
10220 if (NewAlign > Alignment) {
10221 Alignment = NewAlign;
10229 MachineIRBuilder MIB(
MI);
10231 LLT LargestTy = MemOps[0];
10232 for (
unsigned i = 1; i < MemOps.size(); i++)
10234 LargestTy = MemOps[i];
10246 LLT PtrTy = MRI.getType(Dst);
10247 unsigned DstOff = 0;
10248 unsigned Size = KnownLen;
10249 for (
unsigned I = 0;
I < MemOps.size();
I++) {
10250 LLT Ty = MemOps[
I];
10252 if (TySize >
Size) {
10255 assert(
I == MemOps.size() - 1 &&
I != 0);
10256 DstOff -= TySize -
Size;
10266 TLI.isTruncateFree(LargestVT, VT))
10267 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
10280 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
10283 MIB.buildStore(
Value,
Ptr, *StoreMMO);
10288 MI.eraseFromParent();
10294 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10296 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10298 const auto *MMOIt =
MI.memoperands_begin();
10300 bool IsVolatile =
MemOp->isVolatile();
10306 "inline memcpy with dynamic size is not yet supported");
10307 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10308 if (KnownLen == 0) {
10309 MI.eraseFromParent();
10313 const auto &DstMMO = **
MI.memoperands_begin();
10314 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10315 Align DstAlign = DstMMO.getBaseAlign();
10316 Align SrcAlign = SrcMMO.getBaseAlign();
10318 return lowerMemcpyInline(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign,
10325 Align SrcAlign,
bool IsVolatile) {
10326 assert(
MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE);
10327 return lowerMemcpy(
MI, Dst, Src, KnownLen,
10328 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign,
10335 Align SrcAlign,
bool IsVolatile) {
10336 auto &MF = *
MI.getParent()->getParent();
10341 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
10343 bool DstAlignCanChange =
false;
10345 Align Alignment = std::min(DstAlign, SrcAlign);
10349 DstAlignCanChange =
true;
10355 std::vector<LLT> MemOps;
10357 const auto &DstMMO = **
MI.memoperands_begin();
10358 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10364 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10370 if (DstAlignCanChange) {
10373 Align NewAlign =
DL.getABITypeAlign(IRTy);
10378 if (!
TRI->hasStackRealignment(MF))
10380 NewAlign = std::min(NewAlign, *StackAlign);
10382 if (NewAlign > Alignment) {
10383 Alignment = NewAlign;
10391 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
10393 MachineIRBuilder MIB(
MI);
10399 unsigned CurrOffset = 0;
10400 unsigned Size = KnownLen;
10401 for (
auto CopyTy : MemOps) {
10404 if (CopyTy.getSizeInBytes() >
Size)
10405 CurrOffset -= CopyTy.getSizeInBytes() -
Size;
10416 if (CurrOffset != 0) {
10417 LLT SrcTy = MRI.getType(Src);
10420 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10422 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
10426 if (CurrOffset != 0) {
10427 LLT DstTy = MRI.getType(Dst);
10428 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10430 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
10431 CurrOffset += CopyTy.getSizeInBytes();
10432 Size -= CopyTy.getSizeInBytes();
10435 MI.eraseFromParent();
10441 uint64_t KnownLen,
Align DstAlign,
Align SrcAlign,
10443 auto &MF = *
MI.getParent()->getParent();
10448 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
10450 bool DstAlignCanChange =
false;
10453 Align Alignment = std::min(DstAlign, SrcAlign);
10455 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
10457 DstAlignCanChange =
true;
10459 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize);
10460 std::vector<LLT> MemOps;
10462 const auto &DstMMO = **
MI.memoperands_begin();
10463 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
10464 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo();
10465 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo();
10472 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign,
10478 if (DstAlignCanChange) {
10481 Align NewAlign =
DL.getABITypeAlign(IRTy);
10486 if (!
TRI->hasStackRealignment(MF))
10487 if (MaybeAlign StackAlign =
DL.getStackAlignment())
10488 NewAlign = std::min(NewAlign, *StackAlign);
10490 if (NewAlign > Alignment) {
10491 Alignment = NewAlign;
10499 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
10501 MachineIRBuilder MIB(
MI);
10505 unsigned CurrOffset = 0;
10506 SmallVector<Register, 16> LoadVals;
10507 for (
auto CopyTy : MemOps) {
10514 if (CurrOffset != 0) {
10515 LLT SrcTy = MRI.getType(Src);
10518 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
10520 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
10521 CurrOffset += CopyTy.getSizeInBytes();
10525 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
10526 LLT CopyTy = MemOps[
I];
10532 if (CurrOffset != 0) {
10533 LLT DstTy = MRI.getType(Dst);
10536 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
10538 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
10541 MI.eraseFromParent();
10547 const unsigned Opc =
MI.getOpcode();
10550 assert((
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMMOVE ||
10551 Opc == TargetOpcode::G_MEMSET) &&
10552 "Expected memcpy like instruction");
10554 auto MMOIt =
MI.memoperands_begin();
10559 auto [Dst, Src, Len] =
MI.getFirst3Regs();
10561 if (
Opc != TargetOpcode::G_MEMSET) {
10562 assert(MMOIt !=
MI.memoperands_end() &&
"Expected a second MMO on MI");
10563 MemOp = *(++MMOIt);
10564 SrcAlign =
MemOp->getBaseAlign();
10569 if (!LenVRegAndVal)
10571 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
10573 if (KnownLen == 0) {
10574 MI.eraseFromParent();
10578 if (MaxLen && KnownLen > MaxLen)
10581 bool IsVolatile =
MemOp->isVolatile();
10582 if (
Opc == TargetOpcode::G_MEMCPY) {
10583 auto &MF = *
MI.getParent()->getParent();
10586 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize);
10587 return lowerMemcpy(
MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign,
10590 if (
Opc == TargetOpcode::G_MEMMOVE)
10591 return lowerMemmove(
MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
10592 if (
Opc == TargetOpcode::G_MEMSET)
10593 return lowerMemset(
MI, Dst, Src, KnownLen, DstAlign, IsVolatile);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static bool findGISelOptimalMemOpLowering(std::vector< LLT > &MemOps, unsigned Limit, const MemOp &Op, unsigned DstAS, unsigned SrcAS, const AttributeList &FuncAttributes, const TargetLowering &TLI)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static LegalizerHelper::LegalizeResult conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, Type *FromType, LostDebugLocObserver &LocObserver, const TargetLowering &TLI, bool IsSigned=false)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static LegalizerHelper::LegalizeResult simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver)
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static bool shouldLowerMemFuncForSize(const MachineFunction &MF)
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static LegalizerHelper::LegalizeResult createAtomicLibcall(MachineIRBuilder &MIRBuilder, MachineInstr &MI)
static RTLIB::Libcall getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI)
static std::pair< int, int > getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy)
Try to break down OrigTy into NarrowTy sized pieces.
static bool hasSameNumEltsOnAllVectorOperands(GenericMachineInstr &MI, MachineRegisterInfo &MRI, std::initializer_list< unsigned > NonVecOpIndices)
Check that all vector operands have same number of elements.
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg, LLT VecTy)
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, Type *FromType)
static void getUnmergeResults(SmallVectorImpl< Register > &Regs, const MachineInstr &MI)
Append the result registers of G_UNMERGE_VALUES MI to Regs.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
#define RTLIBCASE(LibcallPrefix)
static Type * getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Tracks DebugLocs between checkpoints and verifies that they are transferred.
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file describes how to lower LLVM code to machine code.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
APInt bitcastToAPInt() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
void negate()
Negate this APInt in place.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, unsigned hiBit)
Wrap version of getBitsSet.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Represents a insert subvector.
Register getSubVec() const
Register getBigVec() const
uint64_t getIndexImm() const
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
Represents a threeway compare.
Register getValueReg() const
Get the stored value register.
A base class for all GenericMachineInstrs.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr ElementCount getElementCount() const
constexpr LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr LLT getScalarType() const
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
static constexpr LLT scalarOrVector(ElementCount EC, LLT ScalarTy)
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerThreewayCompare(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI)
LLVM_ABI LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI)
Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
LLVM_ABI LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty)
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerSMULH_UMULH(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerLoad(GAnyLoad &MI)
LLVM_ABI LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerAbsToAddXor(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizeResult lowerFConstant(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerBitreverse(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
Legalize a vector instruction by increasing the number of vector elements involved and ignoring the a...
LLVM_ABI LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy)
Multi-way shift legalization: directly split wide shifts into target-sized parts in a single step,...
LLVM_ABI LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI)
LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI Register buildConstantShiftPart(unsigned Opcode, unsigned PartIdx, unsigned NumParts, ArrayRef< Register > SrcParts, const ShiftParams &Params, LLT TargetTy, LLT ShiftAmtTy)
Generates a single output part for constant shifts using direct indexing.
LLVM_ABI void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by truncating the operand's ty...
LLVM_ABI LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI, unsigned NumElts)
LLVM_ABI LegalizeResult lowerFPTOUI(MachineInstr &MI)
const TargetLowering & getTargetLowering() const
LLVM_ABI LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
LLVM_ABI LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult bitcastInsertSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_INSERT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult lowerUnmergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by replacing the value type.
LLVM_ABI LegalizeResult scalarizeVectorBooleanStore(GStore &MI)
Given a store of a boolean vector, scalarize it.
LLVM_ABI LegalizeResult lowerBitcast(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerReadWriteRegister(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, LLT HalfTy, LLT ShiftAmtTy)
LLVM_ABI LegalizeResult lowerISFPCLASS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFAbs(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerVectorReduction(MachineInstr &MI)
const LegalizerInfo & getLegalizerInfo() const
Expose LegalizerInfo so the clients can re-use.
LLVM_ABI LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult fewerElementsVectorMultiEltType(GenericMachineInstr &MI, unsigned NumElts, std::initializer_list< unsigned > NonVecOpIndices={})
Handles most opcodes.
LLVM_ABI LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarShiftByConstantMultiway(MachineInstr &MI, const APInt &Amt, LLT TargetTy, LLT ShiftAmtTy)
Optimized path for constant shift amounts using static indexing.
LLVM_ABI MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val)
Create a store of Val to a stack temporary and return a load as the same type as Res.
LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ AlreadyLegal
Instruction was already legal and no change was made to the MachineFunction.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFCopySign(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B)
LLVM_ABI LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
LLVM_ABI LegalizeResult lowerFunnelShift(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFPTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
LLVM_ABI LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
LLVM_ABI LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerFFloor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult fewerElementsVectorSeqReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize, Align Alignment, LLT PtrTy)
LLVM_ABI LegalizeResult lowerFPTOSI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerUITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerShuffleVector(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerMergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerVECTOR_COMPRESS(MachineInstr &MI)
LLVM_ABI void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by producing a vector with und...
LLVM_ABI LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF32WithSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0)
LLVM_ABI Register coerceToScalar(Register Val)
Cast the given value to an LLT::scalar with an equivalent size.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI LegalizeResult lowerTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBswap(MachineInstr &MI)
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
LLVM_ABI LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const
Return the alignment to use for a stack temporary object with the given type.
LLVM_ABI LegalizeResult lowerConstant(MachineInstr &MI)
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LLVM_ABI LegalizeResult legalizeInstrStep(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Replace MI by a sequence of legal instructions that can implement the same operation.
TypeSize getValue() const
void checkpoint(bool CheckDebugLocs=true)
Call this to indicate that it's a good point to assess whether locations have been lost.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
LLVM_ABI StringRef getString() const
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
LLVM_ABI iterator getFirstTerminatorForward()
Finds the first terminator in a block by scanning forward.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_UREM Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0)
Build and insert integer negation Zero = G_CONSTANT 0 Res = G_SUB Zero, Op0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_UITOFP Src0.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
MachineInstrBuilder buildXor(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_XOR Op0, Op1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
virtual bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *=nullptr) const
Determine if the target supports unaligned memory accesses.
virtual LLT getOptimalMemOpLLT(const MemOp &Op, const AttributeList &) const
LLT returning variant.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const
Returns true if arguments should be sign-extended in lib calls.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
const Triple & getTargetTriple() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const CallLowering * getCallLowering() const
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, DriverKit, XROS, or bridgeOS).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Type * getType() const
All values are typed, get the type of this value.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ Custom
The target wants to do something special with this combination of operand and type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
FunctionAddr VTableAddr Value
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
LLVM_ABI LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver)
Create a libcall to memcpy et al.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI LegalizerHelper::LegalizeResult createLibcall(MachineIRBuilder &MIRBuilder, const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr)
Helper function that creates a libcall to the given Name using the given calling convention CC.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI)
Returns true if Val can be assumed to never be a signaling NaN.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static LLVM_ABI const fltSemantics & IEEEsingle() LLVM_READNONE
static constexpr roundingMode rmNearestTiesToEven
static constexpr roundingMode rmTowardZero
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE
opStatus
IEEE-754R 7: Default exception handling.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
static MemOp Set(uint64_t Size, bool DstAlignCanChange, Align DstAlign, bool IsZeroMemset, bool IsVolatile)
static MemOp Copy(uint64_t Size, bool DstAlignCanChange, Align DstAlign, Align SrcAlign, bool IsVolatile, bool MemcpyStrSrc=false)