44#define DEBUG_TYPE "legalizer"
57static std::pair<int, int>
63 unsigned NumParts =
Size / NarrowSize;
64 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
67 if (LeftoverSize == 0)
72 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
130 auto Step = LI.getAction(
MI, MRI);
131 switch (Step.Action) {
146 return bitcast(
MI, Step.TypeIdx, Step.NewType);
149 return lower(
MI, Step.TypeIdx, Step.NewType);
158 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
166void LegalizerHelper::insertParts(
Register DstReg,
188 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
190 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
191 return mergeMixedSubvectors(DstReg, AllRegs);
197 extractGCDType(GCDRegs, GCDTy, PartReg);
198 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
199 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
204 LLT Ty = MRI.getType(
Reg);
212void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
215 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
216 appendVectorElts(AllElts, PartRegs[i]);
219 if (!MRI.getType(Leftover).isVector())
222 appendVectorElts(AllElts, Leftover);
224 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
230 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
232 const int StartIdx = Regs.
size();
233 const int NumResults =
MI.getNumOperands() - 1;
235 for (
int I = 0;
I != NumResults; ++
I)
236 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
241 LLT SrcTy = MRI.getType(SrcReg);
242 if (SrcTy == GCDTy) {
248 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
255 LLT SrcTy = MRI.getType(SrcReg);
257 extractGCDType(Parts, GCDTy, SrcReg);
261LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
263 unsigned PadStrategy) {
268 int NumOrigSrc = VRegs.
size();
274 if (NumOrigSrc < NumParts * NumSubParts) {
275 if (PadStrategy == TargetOpcode::G_ZEXT)
276 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
277 else if (PadStrategy == TargetOpcode::G_ANYEXT)
278 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
280 assert(PadStrategy == TargetOpcode::G_SEXT);
285 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
301 for (
int I = 0;
I != NumParts; ++
I) {
302 bool AllMergePartsArePadding =
true;
305 for (
int J = 0; J != NumSubParts; ++J) {
306 int Idx =
I * NumSubParts + J;
307 if (Idx >= NumOrigSrc) {
308 SubMerge[J] = PadReg;
312 SubMerge[J] = VRegs[
Idx];
315 AllMergePartsArePadding =
false;
321 if (AllMergePartsArePadding && !AllPadReg) {
322 if (PadStrategy == TargetOpcode::G_ANYEXT)
323 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
324 else if (PadStrategy == TargetOpcode::G_ZEXT)
325 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
334 Remerge[
I] = AllPadReg;
338 if (NumSubParts == 1)
339 Remerge[
I] = SubMerge[0];
341 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
344 if (AllMergePartsArePadding && !AllPadReg)
345 AllPadReg = Remerge[
I];
348 VRegs = std::move(Remerge);
352void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
354 LLT DstTy = MRI.getType(DstReg);
359 if (DstTy == LCMTy) {
360 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
364 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
373 UnmergeDefs[0] = DstReg;
374 for (
unsigned I = 1;
I != NumDefs; ++
I)
375 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
378 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
386#define RTLIBCASE_INT(LibcallPrefix) \
390 return RTLIB::LibcallPrefix##32; \
392 return RTLIB::LibcallPrefix##64; \
394 return RTLIB::LibcallPrefix##128; \
396 llvm_unreachable("unexpected size"); \
400#define RTLIBCASE(LibcallPrefix) \
404 return RTLIB::LibcallPrefix##32; \
406 return RTLIB::LibcallPrefix##64; \
408 return RTLIB::LibcallPrefix##80; \
410 return RTLIB::LibcallPrefix##128; \
412 llvm_unreachable("unexpected size"); \
417 case TargetOpcode::G_LROUND:
419 case TargetOpcode::G_LLROUND:
421 case TargetOpcode::G_MUL:
423 case TargetOpcode::G_SDIV:
425 case TargetOpcode::G_UDIV:
427 case TargetOpcode::G_SREM:
429 case TargetOpcode::G_UREM:
431 case TargetOpcode::G_CTLZ_ZERO_POISON:
433 case TargetOpcode::G_FADD:
435 case TargetOpcode::G_FSUB:
437 case TargetOpcode::G_FMUL:
439 case TargetOpcode::G_FDIV:
441 case TargetOpcode::G_FEXP:
443 case TargetOpcode::G_FEXP2:
445 case TargetOpcode::G_FEXP10:
447 case TargetOpcode::G_FREM:
449 case TargetOpcode::G_FPOW:
451 case TargetOpcode::G_FPOWI:
453 case TargetOpcode::G_FMA:
455 case TargetOpcode::G_FSIN:
457 case TargetOpcode::G_FCOS:
459 case TargetOpcode::G_FTAN:
461 case TargetOpcode::G_FASIN:
463 case TargetOpcode::G_FACOS:
465 case TargetOpcode::G_FATAN:
467 case TargetOpcode::G_FATAN2:
469 case TargetOpcode::G_FSINH:
471 case TargetOpcode::G_FCOSH:
473 case TargetOpcode::G_FTANH:
475 case TargetOpcode::G_FSINCOS:
477 case TargetOpcode::G_FMODF:
479 case TargetOpcode::G_FLOG10:
481 case TargetOpcode::G_FLOG:
483 case TargetOpcode::G_FLOG2:
485 case TargetOpcode::G_FLDEXP:
487 case TargetOpcode::G_FCEIL:
489 case TargetOpcode::G_FFLOOR:
491 case TargetOpcode::G_FMINNUM:
493 case TargetOpcode::G_FMAXNUM:
495 case TargetOpcode::G_FMINIMUMNUM:
497 case TargetOpcode::G_FMAXIMUMNUM:
499 case TargetOpcode::G_FSQRT:
501 case TargetOpcode::G_FRINT:
503 case TargetOpcode::G_FNEARBYINT:
505 case TargetOpcode::G_INTRINSIC_TRUNC:
507 case TargetOpcode::G_INTRINSIC_ROUND:
509 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
511 case TargetOpcode::G_INTRINSIC_LRINT:
513 case TargetOpcode::G_INTRINSIC_LLRINT:
525 Attribute::SwiftError);
541 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
542 .removeAttribute(Attribute::NoAlias)
543 .removeAttribute(Attribute::NonNull)
548 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
549 CallerAttrs.hasRetAttr(Attribute::SExt))
553 if (
F.getFnAttribute(
"disable-tail-calls").getValueAsBool())
564 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
571 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
579 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
582 if (Ret->getNumImplicitOperands() != 1)
585 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
602 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
607 Info.OrigRet = Result;
610 (Result.Ty->isVoidTy() ||
611 Result.Ty ==
MIRBuilder.getMF().getFunction().getReturnType()) &&
622 if (
MI && Info.LoweredTailCall) {
623 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
633 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
634 "Expected instr following MI to be return or debug inst?");
637 Next->eraseFromParent();
638 }
while (
MI->getNextNode());
653 RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(
Libcall);
654 if (LibcallImpl == RTLIB::Unsupported)
658 const CallingConv::ID CC = Libcalls->getLibcallImplCallingConv(LibcallImpl);
672 Args.push_back({MO.getReg(), OpType, 0});
691 unsigned AddrSpace =
DL.getAllocaAddrSpace();
709 if (LibcallResult != LegalizeResult::Legalized)
717 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
718 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
719 MI.eraseFromParent();
734 LLT DstTy = MRI.getType(DstFrac);
739 unsigned AddrSpace =
DL.getAllocaAddrSpace();
740 MachinePointerInfo PtrInfo;
749 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
752 if (LibcallResult != LegalizeResult::Legalized)
758 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
759 MI.eraseFromParent();
770 case TargetOpcode::G_FPEXT:
772 case TargetOpcode::G_FPTRUNC:
774 case TargetOpcode::G_FPTOSI:
776 case TargetOpcode::G_FPTOUI:
778 case TargetOpcode::G_SITOFP:
780 case TargetOpcode::G_UITOFP:
790 if (FromType->isIntegerTy()) {
791 if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
792 Arg.
Flags[0].setSExt();
794 Arg.
Flags[0].setZExt();
805 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
809 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
813 LLT OpLLT = MRI.getType(Reg);
819 Args.push_back({Reg,
OpTy, 0});
822 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
823 RTLIB::Libcall RTLibcall;
824 unsigned Opc =
MI.getOpcode();
826 case TargetOpcode::G_BZERO:
827 RTLibcall = RTLIB::BZERO;
829 case TargetOpcode::G_MEMCPY:
830 RTLibcall = RTLIB::MEMCPY;
831 Args[0].Flags[0].setReturned();
833 case TargetOpcode::G_MEMMOVE:
834 RTLibcall = RTLIB::MEMMOVE;
835 Args[0].Flags[0].setReturned();
837 case TargetOpcode::G_MEMSET:
838 RTLibcall = RTLIB::MEMSET;
839 Args[0].Flags[0].setReturned();
848 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
851 if (RTLibcallImpl == RTLIB::Unsupported) {
858 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
865 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
875 if (Info.LoweredTailCall) {
876 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
886 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
887 "Expected instr following MI to be return or debug inst?");
890 Next->eraseFromParent();
891 }
while (
MI.getNextNode());
901 unsigned Opc =
MI.getOpcode();
903 auto &MMO = AtomicMI.getMMO();
904 auto Ordering = MMO.getMergedOrdering();
905 LLT MemType = MMO.getMemoryType();
908 return RTLIB::UNKNOWN_LIBCALL;
910#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
912 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
914 case TargetOpcode::G_ATOMIC_CMPXCHG:
915 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
916 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
917 return getOutlineAtomicHelper(LC, Ordering, MemSize);
919 case TargetOpcode::G_ATOMICRMW_XCHG: {
920 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
921 return getOutlineAtomicHelper(LC, Ordering, MemSize);
923 case TargetOpcode::G_ATOMICRMW_ADD:
924 case TargetOpcode::G_ATOMICRMW_SUB: {
925 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
926 return getOutlineAtomicHelper(LC, Ordering, MemSize);
928 case TargetOpcode::G_ATOMICRMW_AND: {
929 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
930 return getOutlineAtomicHelper(LC, Ordering, MemSize);
932 case TargetOpcode::G_ATOMICRMW_OR: {
933 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
934 return getOutlineAtomicHelper(LC, Ordering, MemSize);
936 case TargetOpcode::G_ATOMICRMW_XOR: {
937 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
938 return getOutlineAtomicHelper(LC, Ordering, MemSize);
941 return RTLIB::UNKNOWN_LIBCALL;
954 unsigned Opc =
MI.getOpcode();
956 case TargetOpcode::G_ATOMIC_CMPXCHG:
957 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
960 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
961 MI.getFirst4RegLLTs();
964 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
965 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
966 NewLLT) =
MI.getFirst5RegLLTs();
976 case TargetOpcode::G_ATOMICRMW_XCHG:
977 case TargetOpcode::G_ATOMICRMW_ADD:
978 case TargetOpcode::G_ATOMICRMW_SUB:
979 case TargetOpcode::G_ATOMICRMW_AND:
980 case TargetOpcode::G_ATOMICRMW_OR:
981 case TargetOpcode::G_ATOMICRMW_XOR: {
982 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
985 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
989 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
1004 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
1006 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
1009 if (RTLibcallImpl == RTLIB::Unsupported) {
1016 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
1030static RTLIB::Libcall
1032 RTLIB::Libcall RTLibcall;
1033 switch (
MI.getOpcode()) {
1034 case TargetOpcode::G_GET_FPENV:
1035 RTLibcall = RTLIB::FEGETENV;
1037 case TargetOpcode::G_SET_FPENV:
1038 case TargetOpcode::G_RESET_FPENV:
1039 RTLibcall = RTLIB::FESETENV;
1041 case TargetOpcode::G_GET_FPMODE:
1042 RTLibcall = RTLIB::FEGETMODE;
1044 case TargetOpcode::G_SET_FPMODE:
1045 case TargetOpcode::G_RESET_FPMODE:
1046 RTLibcall = RTLIB::FESETMODE;
1078 LLT StateTy = MRI.getType(Dst);
1081 MachinePointerInfo TempPtrInfo;
1085 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1090 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
1098 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1116 LLT StateTy = MRI.getType(Src);
1119 MachinePointerInfo TempPtrInfo;
1128 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1133 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1134 LocObserver,
nullptr);
1140static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1142#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1146 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1148 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1150 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1152 llvm_unreachable("unexpected size"); \
1185 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1188 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1195 LLT DstTy = MRI.getType(DstReg);
1196 const auto Cond =
Cmp->getCond();
1197 Type *RetTy = TLI.getCmpLibcallReturnType(Ctx);
1202 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1207 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1211 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1218 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1224 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1226 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1239 const auto [OeqLibcall, OeqPred] =
1241 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1243 const auto [UnoLibcall, UnoPred] =
1245 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1260 const auto [OeqLibcall, OeqPred] =
1265 const auto [UnoLibcall, UnoPred] =
1270 if (NotOeq && NotUno)
1289 const auto [InversedLibcall, InversedPred] =
1291 if (!BuildLibcall(InversedLibcall,
1316 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1318 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1321 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1327 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1332 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1334 switch (
MI.getOpcode()) {
1337 case TargetOpcode::G_MUL:
1338 case TargetOpcode::G_SDIV:
1339 case TargetOpcode::G_UDIV:
1340 case TargetOpcode::G_SREM:
1341 case TargetOpcode::G_UREM:
1342 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1343 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1351 case TargetOpcode::G_FADD:
1352 case TargetOpcode::G_FSUB:
1353 case TargetOpcode::G_FMUL:
1354 case TargetOpcode::G_FDIV:
1355 case TargetOpcode::G_FMA:
1356 case TargetOpcode::G_FPOW:
1357 case TargetOpcode::G_FREM:
1358 case TargetOpcode::G_FCOS:
1359 case TargetOpcode::G_FSIN:
1360 case TargetOpcode::G_FTAN:
1361 case TargetOpcode::G_FACOS:
1362 case TargetOpcode::G_FASIN:
1363 case TargetOpcode::G_FATAN:
1364 case TargetOpcode::G_FATAN2:
1365 case TargetOpcode::G_FCOSH:
1366 case TargetOpcode::G_FSINH:
1367 case TargetOpcode::G_FTANH:
1368 case TargetOpcode::G_FLOG10:
1369 case TargetOpcode::G_FLOG:
1370 case TargetOpcode::G_FLOG2:
1371 case TargetOpcode::G_FEXP:
1372 case TargetOpcode::G_FEXP2:
1373 case TargetOpcode::G_FEXP10:
1374 case TargetOpcode::G_FCEIL:
1375 case TargetOpcode::G_FFLOOR:
1376 case TargetOpcode::G_FMINNUM:
1377 case TargetOpcode::G_FMAXNUM:
1378 case TargetOpcode::G_FMINIMUMNUM:
1379 case TargetOpcode::G_FMAXIMUMNUM:
1380 case TargetOpcode::G_FSQRT:
1381 case TargetOpcode::G_FRINT:
1382 case TargetOpcode::G_FNEARBYINT:
1383 case TargetOpcode::G_INTRINSIC_TRUNC:
1384 case TargetOpcode::G_INTRINSIC_ROUND:
1385 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1386 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1390 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1398 case TargetOpcode::G_FSINCOS: {
1399 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1403 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1408 case TargetOpcode::G_FMODF: {
1409 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1413 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1418 case TargetOpcode::G_LROUND:
1419 case TargetOpcode::G_LLROUND:
1420 case TargetOpcode::G_INTRINSIC_LRINT:
1421 case TargetOpcode::G_INTRINSIC_LLRINT: {
1422 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1426 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1428 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1434 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1437 MI.eraseFromParent();
1440 case TargetOpcode::G_FPOWI:
1441 case TargetOpcode::G_FLDEXP: {
1442 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1446 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1448 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1453 {
MI.getOperand(1).getReg(), HLTy, 0},
1454 {
MI.getOperand(2).getReg(), ITy, 1}};
1455 Args[1].Flags[0].setSExt();
1457 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1462 case TargetOpcode::G_FPEXT:
1463 case TargetOpcode::G_FPTRUNC: {
1466 if (!FromTy || !ToTy)
1473 case TargetOpcode::G_FCMP: {
1477 MI.eraseFromParent();
1480 case TargetOpcode::G_FPTOSI:
1481 case TargetOpcode::G_FPTOUI: {
1485 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1486 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1489 FromTy, LocObserver);
1494 case TargetOpcode::G_SITOFP:
1495 case TargetOpcode::G_UITOFP: {
1496 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1499 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1501 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1508 case TargetOpcode::G_ATOMICRMW_XCHG:
1509 case TargetOpcode::G_ATOMICRMW_ADD:
1510 case TargetOpcode::G_ATOMICRMW_SUB:
1511 case TargetOpcode::G_ATOMICRMW_AND:
1512 case TargetOpcode::G_ATOMICRMW_OR:
1513 case TargetOpcode::G_ATOMICRMW_XOR:
1514 case TargetOpcode::G_ATOMIC_CMPXCHG:
1515 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1521 case TargetOpcode::G_BZERO:
1522 case TargetOpcode::G_MEMCPY:
1523 case TargetOpcode::G_MEMMOVE:
1524 case TargetOpcode::G_MEMSET: {
1529 MI.eraseFromParent();
1532 case TargetOpcode::G_GET_FPENV:
1533 case TargetOpcode::G_GET_FPMODE: {
1539 case TargetOpcode::G_SET_FPENV:
1540 case TargetOpcode::G_SET_FPMODE: {
1546 case TargetOpcode::G_RESET_FPENV:
1547 case TargetOpcode::G_RESET_FPMODE: {
1555 MI.eraseFromParent();
1562 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1565 switch (
MI.getOpcode()) {
1568 case TargetOpcode::G_IMPLICIT_DEF: {
1570 LLT DstTy = MRI.getType(DstReg);
1578 if (SizeOp0 % NarrowSize != 0) {
1583 MI.eraseFromParent();
1587 int NumParts = SizeOp0 / NarrowSize;
1590 for (
int i = 0; i < NumParts; ++i)
1594 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1596 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1597 MI.eraseFromParent();
1600 case TargetOpcode::G_CONSTANT: {
1601 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1602 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1603 unsigned TotalSize = Ty.getSizeInBits();
1605 int NumParts = TotalSize / NarrowSize;
1608 for (
int I = 0;
I != NumParts; ++
I) {
1609 unsigned Offset =
I * NarrowSize;
1616 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1618 if (LeftoverBits != 0) {
1622 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1626 insertParts(
MI.getOperand(0).getReg(),
1627 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1629 MI.eraseFromParent();
1632 case TargetOpcode::G_SEXT:
1633 case TargetOpcode::G_ZEXT:
1634 case TargetOpcode::G_ANYEXT:
1636 case TargetOpcode::G_TRUNC: {
1640 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1642 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1646 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1647 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1648 MI.eraseFromParent();
1651 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1652 case TargetOpcode::G_FREEZE: {
1656 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1661 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1663 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1665 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1669 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1670 MI.eraseFromParent();
1673 case TargetOpcode::G_ADD:
1674 case TargetOpcode::G_SUB:
1675 case TargetOpcode::G_SADDO:
1676 case TargetOpcode::G_SSUBO:
1677 case TargetOpcode::G_SADDE:
1678 case TargetOpcode::G_SSUBE:
1679 case TargetOpcode::G_UADDO:
1680 case TargetOpcode::G_USUBO:
1681 case TargetOpcode::G_UADDE:
1682 case TargetOpcode::G_USUBE:
1684 case TargetOpcode::G_MUL:
1685 case TargetOpcode::G_UMULH:
1687 case TargetOpcode::G_EXTRACT:
1689 case TargetOpcode::G_INSERT:
1691 case TargetOpcode::G_LOAD: {
1693 Register DstReg = LoadMI.getDstReg();
1694 LLT DstTy = MRI.getType(DstReg);
1698 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1699 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1700 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1702 LoadMI.eraseFromParent();
1708 case TargetOpcode::G_ZEXTLOAD:
1709 case TargetOpcode::G_SEXTLOAD:
1710 case TargetOpcode::G_FPEXTLOAD: {
1712 Register DstReg = LoadMI.getDstReg();
1713 Register PtrReg = LoadMI.getPointerReg();
1715 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1716 auto &MMO = LoadMI.getMMO();
1719 if (MemSize == NarrowSize) {
1721 }
else if (MemSize < NarrowSize) {
1722 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1723 }
else if (MemSize > NarrowSize) {
1735 LoadMI.eraseFromParent();
1738 case TargetOpcode::G_STORE: {
1741 Register SrcReg = StoreMI.getValueReg();
1742 LLT SrcTy = MRI.getType(SrcReg);
1743 if (SrcTy.isVector())
1746 int NumParts = SizeOp0 / NarrowSize;
1748 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1749 if (SrcTy.isVector() && LeftoverBits != 0)
1752 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1753 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1755 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1756 StoreMI.eraseFromParent();
1762 case TargetOpcode::G_FPTRUNCSTORE: {
1764 Register SrcReg = StoreMI.getValueReg();
1765 Register PtrReg = StoreMI.getPointerReg();
1767 auto &MMO = StoreMI.getMMO();
1769 if (MemSize > NarrowSize) {
1773 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1774 if (MemSize == NarrowSize) {
1776 }
else if (MemSize < NarrowSize) {
1777 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1781 StoreMI.eraseFromParent();
1784 case TargetOpcode::G_SELECT:
1786 case TargetOpcode::G_AND:
1787 case TargetOpcode::G_OR:
1788 case TargetOpcode::G_XOR: {
1800 case TargetOpcode::G_SHL:
1801 case TargetOpcode::G_LSHR:
1802 case TargetOpcode::G_ASHR:
1804 case TargetOpcode::G_CTLZ:
1805 case TargetOpcode::G_CTLZ_ZERO_POISON:
1806 case TargetOpcode::G_CTTZ:
1807 case TargetOpcode::G_CTTZ_ZERO_POISON:
1808 case TargetOpcode::G_CTLS:
1809 case TargetOpcode::G_CTPOP:
1811 switch (
MI.getOpcode()) {
1812 case TargetOpcode::G_CTLZ:
1813 case TargetOpcode::G_CTLZ_ZERO_POISON:
1815 case TargetOpcode::G_CTTZ:
1816 case TargetOpcode::G_CTTZ_ZERO_POISON:
1818 case TargetOpcode::G_CTPOP:
1820 case TargetOpcode::G_CTLS:
1830 case TargetOpcode::G_INTTOPTR:
1838 case TargetOpcode::G_PTRTOINT:
1846 case TargetOpcode::G_PHI: {
1849 if (SizeOp0 % NarrowSize != 0)
1852 unsigned NumParts = SizeOp0 / NarrowSize;
1856 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1864 for (
unsigned i = 0; i < NumParts; ++i) {
1865 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1867 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1868 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1869 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1872 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1874 MI.eraseFromParent();
1877 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1878 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1882 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1888 case TargetOpcode::G_ICMP: {
1890 LLT SrcTy = MRI.getType(LHS);
1896 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1902 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1903 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1909 LLT ResTy = MRI.getType(Dst);
1914 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1916 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1917 auto LHS = std::get<0>(LHSAndRHS);
1918 auto RHS = std::get<1>(LHSAndRHS);
1919 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1926 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1927 auto LHS = std::get<0>(LHSAndRHS);
1928 auto RHS = std::get<1>(LHSAndRHS);
1929 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1930 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1931 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1932 TargetOpcode::G_ZEXT);
1939 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1940 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1941 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1946 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1950 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1955 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1959 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1962 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1965 LHSPartRegs[
I], RHSPartRegs[
I]);
1966 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1972 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1981 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1985 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1986 RHSLeftoverRegs[
I]);
1988 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1989 RHSLeftoverRegs[
I]);
1992 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1993 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1999 MI.eraseFromParent();
2002 case TargetOpcode::G_FCMP:
2011 case TargetOpcode::G_SEXT_INREG: {
2015 int64_t SizeInBits =
MI.getOperand(2).getImm();
2024 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2025 MO1.
setReg(TruncMIB.getReg(0));
2028 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2040 if (SizeOp0 % NarrowSize != 0)
2042 int NumParts = SizeOp0 / NarrowSize;
2050 for (
int i = 0; i < NumParts; ++i) {
2051 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2066 for (
int i = 0; i < NumParts; ++i) {
2069 PartialExtensionReg = DstRegs.
back();
2071 assert(PartialExtensionReg &&
2072 "Expected to visit partial extension before full");
2073 if (FullExtensionReg) {
2078 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2080 FullExtensionReg = DstRegs.
back();
2085 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2088 PartialExtensionReg = DstRegs.
back();
2094 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2095 MI.eraseFromParent();
2098 case TargetOpcode::G_BSWAP:
2099 case TargetOpcode::G_BITREVERSE: {
2100 if (SizeOp0 % NarrowSize != 0)
2105 unsigned NumParts = SizeOp0 / NarrowSize;
2106 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2109 for (
unsigned i = 0; i < NumParts; ++i) {
2110 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2111 {SrcRegs[NumParts - 1 - i]});
2115 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2118 MI.eraseFromParent();
2121 case TargetOpcode::G_PTR_ADD:
2122 case TargetOpcode::G_PTRMASK: {
2130 case TargetOpcode::G_FPTOUI:
2131 case TargetOpcode::G_FPTOSI:
2132 case TargetOpcode::G_FPTOUI_SAT:
2133 case TargetOpcode::G_FPTOSI_SAT:
2135 case TargetOpcode::G_FPEXT:
2142 case TargetOpcode::G_FLDEXP:
2143 case TargetOpcode::G_STRICT_FLDEXP:
2145 case TargetOpcode::G_VSCALE: {
2147 LLT Ty = MRI.getType(Dst);
2151 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2152 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2153 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2156 MI.eraseFromParent();
2163 LLT Ty = MRI.getType(Val);
2164 if (Ty.isScalar() && !Ty.isFloat())
2171 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2173 if (Ty.isPointer()) {
2174 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2176 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2182 if (Ty.isPointerVector())
2183 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2184 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2188 unsigned OpIdx,
unsigned ExtOpcode) {
2190 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2191 MO.
setReg(ExtB.getReg(0));
2197 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2199 MO.
setReg(ExtB.getReg(0));
2205 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2206 MO.
setReg(ExtB.getReg(0));
2210 unsigned OpIdx,
unsigned TruncOpcode) {
2212 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2214 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2221 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2223 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2228 unsigned OpIdx,
unsigned ExtOpcode) {
2230 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2232 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2241 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2243 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2249 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2259 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2266LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2271 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2272 if (DstTy.isVector())
2277 const int SrcSize = SrcTy.getSizeInBits();
2279 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2281 unsigned NumOps =
MI.getNumOperands();
2282 unsigned NumSrc =
MI.getNumOperands() - 1;
2283 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2285 if (WideSize >= DstSize) {
2289 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2290 const unsigned Offset = (
I - 1) * PartSize;
2303 ResultReg = NextResult;
2306 if (WideSize > DstSize)
2308 else if (DstTy.isPointer())
2310 else if (DstTy != WideTy)
2313 MI.eraseFromParent();
2338 const int GCD = std::gcd(SrcSize, WideSize);
2348 if (GCD == SrcSize) {
2351 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2352 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2358 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2360 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2364 const int PartsPerGCD = WideSize / GCD;
2368 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2370 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2377 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2379 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2380 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2383 MI.eraseFromParent();
2388LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2393 int NumDst =
MI.getNumOperands() - 1;
2394 Register SrcReg =
MI.getOperand(NumDst).getReg();
2395 LLT SrcTy = MRI.getType(SrcReg);
2399 Register Dst0Reg =
MI.getOperand(0).getReg();
2400 LLT DstTy = MRI.getType(Dst0Reg);
2409 dbgs() <<
"Not casting non-integral address space integer\n");
2414 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2422 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2431 SrcTy = MRI.getType(SrcReg);
2435 for (
int I = 1;
I != NumDst; ++
I) {
2436 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2437 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2441 MI.eraseFromParent();
2452 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2456 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2459 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2477 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2482 if (PartsPerRemerge == 1) {
2485 for (
int I = 0;
I != NumUnmerge; ++
I) {
2486 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2488 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2489 int Idx =
I * PartsPerUnmerge + J;
2491 MIB.addDef(
MI.getOperand(Idx).getReg());
2494 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2498 MIB.addUse(Unmerge.getReg(
I));
2501 SmallVector<Register, 16> Parts;
2502 for (
int J = 0; J != NumUnmerge; ++J)
2503 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2506 for (
int I = 0;
I != NumDst; ++
I) {
2507 for (
int J = 0; J < PartsPerRemerge; ++J) {
2508 const int Idx =
I * PartsPerRemerge + J;
2512 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2513 RemergeParts.
clear();
2517 MI.eraseFromParent();
2522LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2524 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2525 unsigned Offset =
MI.getOperand(2).getImm();
2528 if (SrcTy.
isVector() || DstTy.isVector())
2540 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2544 if (DstTy.isPointer())
2551 MI.eraseFromParent();
2556 LLT ShiftTy = SrcTy;
2565 MI.eraseFromParent();
2596LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2598 if (TypeIdx != 0 || WideTy.
isVector())
2608LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2612 std::optional<Register> CarryIn;
2613 switch (
MI.getOpcode()) {
2616 case TargetOpcode::G_SADDO:
2617 Opcode = TargetOpcode::G_ADD;
2618 ExtOpcode = TargetOpcode::G_SEXT;
2620 case TargetOpcode::G_SSUBO:
2621 Opcode = TargetOpcode::G_SUB;
2622 ExtOpcode = TargetOpcode::G_SEXT;
2624 case TargetOpcode::G_UADDO:
2625 Opcode = TargetOpcode::G_ADD;
2626 ExtOpcode = TargetOpcode::G_ZEXT;
2628 case TargetOpcode::G_USUBO:
2629 Opcode = TargetOpcode::G_SUB;
2630 ExtOpcode = TargetOpcode::G_ZEXT;
2632 case TargetOpcode::G_SADDE:
2633 Opcode = TargetOpcode::G_UADDE;
2634 ExtOpcode = TargetOpcode::G_SEXT;
2635 CarryIn =
MI.getOperand(4).getReg();
2637 case TargetOpcode::G_SSUBE:
2638 Opcode = TargetOpcode::G_USUBE;
2639 ExtOpcode = TargetOpcode::G_SEXT;
2640 CarryIn =
MI.getOperand(4).getReg();
2642 case TargetOpcode::G_UADDE:
2643 Opcode = TargetOpcode::G_UADDE;
2644 ExtOpcode = TargetOpcode::G_ZEXT;
2645 CarryIn =
MI.getOperand(4).getReg();
2647 case TargetOpcode::G_USUBE:
2648 Opcode = TargetOpcode::G_USUBE;
2649 ExtOpcode = TargetOpcode::G_ZEXT;
2650 CarryIn =
MI.getOperand(4).getReg();
2666 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2667 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2671 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2673 .buildInstr(Opcode, {WideTy, CarryOutTy},
2674 {LHSExt, RHSExt, *CarryIn})
2677 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2679 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2680 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2681 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2686 MI.eraseFromParent();
2691LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2693 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2694 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2695 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2696 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2697 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2710 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2717 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2721 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2722 {ShiftL, ShiftR},
MI.getFlags());
2727 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2730 MI.eraseFromParent();
2735LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2744 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2746 LLT SrcTy = MRI.getType(
LHS);
2747 LLT OverflowTy = MRI.getType(OriginalOverflow);
2754 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2755 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2756 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2763 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2765 MachineInstrBuilder Mulo;
2766 if (WideMulCanOverflow)
2767 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2768 {LeftOperand, RightOperand});
2770 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2775 MachineInstrBuilder ExtResult;
2782 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2786 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2789 if (WideMulCanOverflow) {
2797 MI.eraseFromParent();
2803 unsigned Opcode =
MI.getOpcode();
2807 case TargetOpcode::G_ATOMICRMW_XCHG:
2808 case TargetOpcode::G_ATOMICRMW_ADD:
2809 case TargetOpcode::G_ATOMICRMW_SUB:
2810 case TargetOpcode::G_ATOMICRMW_AND:
2811 case TargetOpcode::G_ATOMICRMW_OR:
2812 case TargetOpcode::G_ATOMICRMW_XOR:
2813 case TargetOpcode::G_ATOMICRMW_MIN:
2814 case TargetOpcode::G_ATOMICRMW_MAX:
2815 case TargetOpcode::G_ATOMICRMW_UMIN:
2816 case TargetOpcode::G_ATOMICRMW_UMAX:
2817 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2823 case TargetOpcode::G_ATOMIC_CMPXCHG:
2824 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2831 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2841 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2846 case TargetOpcode::G_EXTRACT:
2847 return widenScalarExtract(
MI, TypeIdx, WideTy);
2848 case TargetOpcode::G_INSERT:
2849 return widenScalarInsert(
MI, TypeIdx, WideTy);
2850 case TargetOpcode::G_MERGE_VALUES:
2851 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2852 case TargetOpcode::G_UNMERGE_VALUES:
2853 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2854 case TargetOpcode::G_SADDO:
2855 case TargetOpcode::G_SSUBO:
2856 case TargetOpcode::G_UADDO:
2857 case TargetOpcode::G_USUBO:
2858 case TargetOpcode::G_SADDE:
2859 case TargetOpcode::G_SSUBE:
2860 case TargetOpcode::G_UADDE:
2861 case TargetOpcode::G_USUBE:
2862 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2863 case TargetOpcode::G_UMULO:
2864 case TargetOpcode::G_SMULO:
2865 return widenScalarMulo(
MI, TypeIdx, WideTy);
2866 case TargetOpcode::G_SADDSAT:
2867 case TargetOpcode::G_SSUBSAT:
2868 case TargetOpcode::G_SSHLSAT:
2869 case TargetOpcode::G_UADDSAT:
2870 case TargetOpcode::G_USUBSAT:
2871 case TargetOpcode::G_USHLSAT:
2872 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2873 case TargetOpcode::G_CTTZ:
2874 case TargetOpcode::G_CTTZ_ZERO_POISON:
2875 case TargetOpcode::G_CTLZ:
2876 case TargetOpcode::G_CTLZ_ZERO_POISON:
2877 case TargetOpcode::G_CTLS:
2878 case TargetOpcode::G_CTPOP: {
2891 case TargetOpcode::G_CTTZ:
2892 case TargetOpcode::G_CTTZ_ZERO_POISON:
2893 case TargetOpcode::G_CTLZ_ZERO_POISON:
2894 ExtOpc = TargetOpcode::G_ANYEXT;
2896 case TargetOpcode::G_CTLS:
2897 ExtOpc = TargetOpcode::G_SEXT;
2900 ExtOpc = TargetOpcode::G_ZEXT;
2903 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2904 LLT CurTy = MRI.getType(SrcReg);
2905 unsigned NewOpc = Opcode;
2906 if (NewOpc == TargetOpcode::G_CTTZ) {
2913 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2915 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2921 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2931 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2933 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2938 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2939 Opcode == TargetOpcode::G_CTLZ
2944 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2945 MI.eraseFromParent();
2948 case TargetOpcode::G_BSWAP: {
2952 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2953 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2954 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2957 MI.getOperand(0).setReg(DstExt);
2961 LLT Ty = MRI.getType(DstReg);
2963 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2964 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2970 case TargetOpcode::G_BITREVERSE: {
2974 LLT Ty = MRI.getType(DstReg);
2977 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2979 MI.getOperand(0).setReg(DstExt);
2982 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2983 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2988 case TargetOpcode::G_FREEZE:
2989 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2996 case TargetOpcode::G_ABS:
3003 case TargetOpcode::G_ADD:
3004 case TargetOpcode::G_AND:
3005 case TargetOpcode::G_MUL:
3006 case TargetOpcode::G_OR:
3007 case TargetOpcode::G_XOR:
3008 case TargetOpcode::G_SUB:
3009 case TargetOpcode::G_SHUFFLE_VECTOR:
3025 case TargetOpcode::G_SBFX:
3026 case TargetOpcode::G_UBFX:
3040 case TargetOpcode::G_SHL:
3060 case TargetOpcode::G_ROTR:
3061 case TargetOpcode::G_ROTL:
3070 case TargetOpcode::G_SDIV:
3071 case TargetOpcode::G_SREM:
3072 case TargetOpcode::G_SMIN:
3073 case TargetOpcode::G_SMAX:
3074 case TargetOpcode::G_ABDS:
3082 case TargetOpcode::G_SDIVREM:
3092 case TargetOpcode::G_ASHR:
3093 case TargetOpcode::G_LSHR:
3097 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3098 : TargetOpcode::G_ZEXT;
3111 case TargetOpcode::G_UDIV:
3112 case TargetOpcode::G_UREM:
3113 case TargetOpcode::G_ABDU:
3120 case TargetOpcode::G_UDIVREM:
3129 case TargetOpcode::G_UMIN:
3130 case TargetOpcode::G_UMAX: {
3131 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3133 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3137 ? TargetOpcode::G_SEXT
3138 : TargetOpcode::G_ZEXT;
3148 case TargetOpcode::G_SELECT:
3158 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3165 case TargetOpcode::G_FPEXT:
3173 case TargetOpcode::G_FPTOSI:
3174 case TargetOpcode::G_FPTOUI:
3175 case TargetOpcode::G_INTRINSIC_LRINT:
3176 case TargetOpcode::G_INTRINSIC_LLRINT:
3177 case TargetOpcode::G_IS_FPCLASS:
3187 case TargetOpcode::G_SITOFP:
3197 case TargetOpcode::G_UITOFP:
3207 case TargetOpcode::G_FPTOSI_SAT:
3208 case TargetOpcode::G_FPTOUI_SAT:
3213 LLT Ty = MRI.getType(OldDst);
3214 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3216 MI.getOperand(0).setReg(ExtReg);
3217 uint64_t ShortBits = Ty.getScalarSizeInBits();
3220 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3231 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3232 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3240 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3248 case TargetOpcode::G_LOAD:
3249 case TargetOpcode::G_SEXTLOAD:
3250 case TargetOpcode::G_ZEXTLOAD:
3251 case TargetOpcode::G_FPEXTLOAD:
3257 case TargetOpcode::G_STORE: {
3261 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3262 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3263 if (!Ty.isScalar()) {
3271 MI.setMemRefs(MF, {NewMMO});
3278 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3279 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3285 case TargetOpcode::G_FPTRUNCSTORE:
3292 case TargetOpcode::G_CONSTANT: {
3295 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3296 MRI.getType(
MI.getOperand(0).getReg()));
3297 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3298 ExtOpc == TargetOpcode::G_ANYEXT) &&
3301 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3305 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3311 case TargetOpcode::G_FCONSTANT: {
3317 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3319 MI.eraseFromParent();
3322 case TargetOpcode::G_IMPLICIT_DEF: {
3328 case TargetOpcode::G_BRCOND:
3334 case TargetOpcode::G_FCMP:
3345 case TargetOpcode::G_ICMP:
3350 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3354 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3355 unsigned ExtOpcode =
3359 ? TargetOpcode::G_SEXT
3360 : TargetOpcode::G_ZEXT;
3367 case TargetOpcode::G_PTR_ADD:
3368 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3374 case TargetOpcode::G_PHI: {
3375 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3378 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3390 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3393 LLT VecTy = MRI.getType(VecReg);
3397 TargetOpcode::G_ANYEXT);
3411 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3427 LLT VecTy = MRI.getType(VecReg);
3446 case TargetOpcode::G_FADD:
3447 case TargetOpcode::G_FMUL:
3448 case TargetOpcode::G_FSUB:
3449 case TargetOpcode::G_FMA:
3450 case TargetOpcode::G_FMAD:
3451 case TargetOpcode::G_FNEG:
3452 case TargetOpcode::G_FABS:
3453 case TargetOpcode::G_FCANONICALIZE:
3454 case TargetOpcode::G_FMINNUM:
3455 case TargetOpcode::G_FMAXNUM:
3456 case TargetOpcode::G_FMINNUM_IEEE:
3457 case TargetOpcode::G_FMAXNUM_IEEE:
3458 case TargetOpcode::G_FMINIMUM:
3459 case TargetOpcode::G_FMAXIMUM:
3460 case TargetOpcode::G_FMINIMUMNUM:
3461 case TargetOpcode::G_FMAXIMUMNUM:
3462 case TargetOpcode::G_FDIV:
3463 case TargetOpcode::G_FREM:
3464 case TargetOpcode::G_FCEIL:
3465 case TargetOpcode::G_FFLOOR:
3466 case TargetOpcode::G_FCOS:
3467 case TargetOpcode::G_FSIN:
3468 case TargetOpcode::G_FTAN:
3469 case TargetOpcode::G_FACOS:
3470 case TargetOpcode::G_FASIN:
3471 case TargetOpcode::G_FATAN:
3472 case TargetOpcode::G_FATAN2:
3473 case TargetOpcode::G_FCOSH:
3474 case TargetOpcode::G_FSINH:
3475 case TargetOpcode::G_FTANH:
3476 case TargetOpcode::G_FLOG10:
3477 case TargetOpcode::G_FLOG:
3478 case TargetOpcode::G_FLOG2:
3479 case TargetOpcode::G_FRINT:
3480 case TargetOpcode::G_FNEARBYINT:
3481 case TargetOpcode::G_FSQRT:
3482 case TargetOpcode::G_FEXP:
3483 case TargetOpcode::G_FEXP2:
3484 case TargetOpcode::G_FEXP10:
3485 case TargetOpcode::G_FPOW:
3486 case TargetOpcode::G_INTRINSIC_TRUNC:
3487 case TargetOpcode::G_INTRINSIC_ROUND:
3488 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3492 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3498 case TargetOpcode::G_FMODF: {
3508 case TargetOpcode::G_FPOWI:
3509 case TargetOpcode::G_FLDEXP:
3510 case TargetOpcode::G_STRICT_FLDEXP: {
3512 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3533 case TargetOpcode::G_FFREXP: {
3546 case TargetOpcode::G_LROUND:
3547 case TargetOpcode::G_LLROUND:
3558 case TargetOpcode::G_INTTOPTR:
3566 case TargetOpcode::G_PTRTOINT:
3574 case TargetOpcode::G_BUILD_VECTOR: {
3578 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3584 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3592 case TargetOpcode::G_SEXT_INREG:
3601 case TargetOpcode::G_PTRMASK: {
3609 case TargetOpcode::G_VECREDUCE_ADD: {
3618 case TargetOpcode::G_VECREDUCE_FADD:
3619 case TargetOpcode::G_VECREDUCE_FMUL:
3620 case TargetOpcode::G_VECREDUCE_FMIN:
3621 case TargetOpcode::G_VECREDUCE_FMAX:
3622 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3623 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3628 LLT VecTy = MRI.getType(VecReg);
3635 case TargetOpcode::G_VSCALE: {
3642 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3647 case TargetOpcode::G_SPLAT_VECTOR: {
3656 case TargetOpcode::G_INSERT_SUBVECTOR: {
3664 LLT SubVecTy = MRI.getType(SubVec);
3668 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3669 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3670 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3674 auto SplatZero =
MIRBuilder.buildSplatVector(
3679 MI.eraseFromParent();
3683 case TargetOpcode::G_BITCAST:
3695 if (MRI.getType(Dst) == MRI.getType(Src)) {
3696 Observer.changingAllUsesOfReg(MRI, Dst);
3697 MRI.replaceRegWith(Dst, Src);
3698 Observer.finishedChangingAllUsesOfReg();
3699 MI.eraseFromParent();
3708 auto Unmerge =
B.buildUnmerge(Ty, Src);
3709 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3718 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3732 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3741 MI.eraseFromParent();
3752 MI.eraseFromParent();
3759 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3760 if (SrcTy.isVector()) {
3764 if (DstTy.isVector()) {
3779 unsigned PieceSize =
3795 MI.eraseFromParent();
3800 LLT::vector(SrcEC * (SrcEltSize / PieceSize), PieceTy);
3802 MIRBuilder.buildBitcast(PiecesVecTy, Src).getReg(0);
3804 MI.eraseFromParent();
3811 LLT DstCastTy = DstEltTy;
3812 LLT SrcPartTy = SrcEltTy;
3816 if (NumSrcElt < NumDstElt) {
3827 SrcPartTy = SrcEltTy;
3828 }
else if (NumSrcElt > NumDstElt) {
3840 DstCastTy = DstEltTy;
3845 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3849 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3850 MI.eraseFromParent();
3854 if (DstTy.isVector()) {
3857 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3858 MI.eraseFromParent();
3874 unsigned NewEltSize,
3875 unsigned OldEltSize) {
3876 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3877 LLT IdxTy =
B.getMRI()->getType(Idx);
3880 auto OffsetMask =
B.buildConstant(
3882 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3883 return B.buildShl(IdxTy, OffsetIdx,
3884 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3899 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3903 unsigned OldNumElts = SrcVecTy.getNumElements();
3910 if (NewNumElts > OldNumElts) {
3921 if (NewNumElts % OldNumElts != 0)
3925 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3929 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3932 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3934 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3935 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3936 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3937 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3938 NewOps[
I] = Elt.getReg(0);
3941 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3943 MI.eraseFromParent();
3947 if (NewNumElts < OldNumElts) {
3948 if (NewEltSize % OldEltSize != 0)
3970 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3971 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3974 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3978 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3979 ScaledIdx).getReg(0);
3987 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3989 MI.eraseFromParent();
4003 LLT TargetTy =
B.getMRI()->getType(TargetReg);
4004 LLT InsertTy =
B.getMRI()->getType(InsertReg);
4005 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
4006 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
4009 auto EltMask =
B.buildConstant(
4013 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
4014 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
4017 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
4021 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
4035 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
4036 MI.getFirst4RegLLTs();
4048 if (NewNumElts < OldNumElts) {
4049 if (NewEltSize % OldEltSize != 0)
4058 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4059 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4062 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4066 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4067 ScaledIdx).getReg(0);
4077 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4078 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4082 MI.eraseFromParent();
4112 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4116 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4117 return UnableToLegalize;
4122 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4124 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4133 MI.eraseFromParent();
4151 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4152 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4162 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4163 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4165 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4166 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4168 MI.eraseFromParent();
4194 uint64_t Idx = ES->getIndexImm();
4198 LLT DstTy = MRI.getType(Dst);
4199 LLT SrcTy = MRI.getType(Src);
4205 if (DstTy == CastTy)
4213 if (CastEltSize < DstEltSize)
4216 auto AdjustAmt = CastEltSize / DstEltSize;
4217 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4218 SrcTyMinElts % AdjustAmt != 0)
4223 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4224 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4227 ES->eraseFromParent();
4258 uint64_t Idx = ES->getIndexImm();
4262 LLT DstTy = MRI.getType(Dst);
4263 LLT BigVecTy = MRI.getType(BigVec);
4264 LLT SubVecTy = MRI.getType(SubVec);
4266 if (DstTy == CastTy)
4281 if (CastEltSize < DstEltSize)
4284 auto AdjustAmt = CastEltSize / DstEltSize;
4285 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4286 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4292 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4293 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4295 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4298 ES->eraseFromParent();
4306 LLT DstTy = MRI.getType(DstReg);
4316 if (MemSizeInBits != MemStoreSizeInBits) {
4333 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4337 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4338 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4340 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4343 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4345 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4348 if (DstTy != LoadTy)
4356 if (
MIRBuilder.getDataLayout().isBigEndian())
4374 uint64_t LargeSplitSize, SmallSplitSize;
4379 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4386 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4389 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4400 if (Alignment.value() * 8 > MemSizeInBits &&
4405 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4422 LLT PtrTy = MRI.getType(PtrReg);
4428 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4431 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4432 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4433 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4435 SmallPtr, *SmallMMO);
4437 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4438 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4440 if (AnyExtTy == DstTy)
4441 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4443 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4445 if (IntDstTy == DstTy) {
4452 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4458 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4475 LLT SrcTy = MRI.getType(SrcReg);
4483 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4489 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4491 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4495 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4499 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4514 uint64_t LargeSplitSize, SmallSplitSize;
4521 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4524 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4533 if (SrcTy.isPointer()) {
4538 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4541 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4542 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4545 LLT PtrTy = MRI.getType(PtrReg);
4547 LargeSplitSize / 8);
4548 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4554 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4555 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4564 LLT SrcTy = MRI.getType(SrcReg);
4570 assert(SrcTy.isVector() &&
"Expect a vector store type");
4577 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4581 auto Elt =
MIRBuilder.buildExtractVectorElement(
4582 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4583 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4584 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4590 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4591 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4595 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4606 switch (
MI.getOpcode()) {
4607 case TargetOpcode::G_LOAD: {
4625 case TargetOpcode::G_STORE: {
4641 case TargetOpcode::G_SELECT: {
4645 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4647 dbgs() <<
"bitcast action not implemented for vector select\n");
4658 case TargetOpcode::G_AND:
4659 case TargetOpcode::G_OR:
4660 case TargetOpcode::G_XOR: {
4668 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4670 case TargetOpcode::G_INSERT_VECTOR_ELT:
4672 case TargetOpcode::G_CONCAT_VECTORS:
4674 case TargetOpcode::G_SHUFFLE_VECTOR:
4676 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4678 case TargetOpcode::G_INSERT_SUBVECTOR:
4686void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4695 switch(
MI.getOpcode()) {
4698 case TargetOpcode::G_FCONSTANT:
4700 case TargetOpcode::G_BITCAST:
4702 case TargetOpcode::G_SREM:
4703 case TargetOpcode::G_UREM: {
4704 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4706 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4707 {MI.getOperand(1), MI.getOperand(2)});
4709 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4711 MI.eraseFromParent();
4714 case TargetOpcode::G_SADDO:
4715 case TargetOpcode::G_SSUBO:
4717 case TargetOpcode::G_SADDE:
4719 case TargetOpcode::G_SSUBE:
4721 case TargetOpcode::G_UMULH:
4722 case TargetOpcode::G_SMULH:
4724 case TargetOpcode::G_SMULO:
4725 case TargetOpcode::G_UMULO: {
4728 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4729 LLT Ty = MRI.getType(Res);
4731 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4732 ? TargetOpcode::G_SMULH
4733 : TargetOpcode::G_UMULH;
4737 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4738 MI.removeOperand(1);
4741 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4749 if (Opcode == TargetOpcode::G_SMULH) {
4750 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4751 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4758 case TargetOpcode::G_FNEG: {
4759 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4762 Register CastedSubByReg = SubByReg;
4764 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4765 !SubByRegTy.getScalarType().isInteger()) {
4766 auto BitcastDst = SubByRegTy.changeElementType(
4768 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4774 if (ResTy != TyInt) {
4776 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4779 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4781 MI.eraseFromParent();
4784 case TargetOpcode::G_FSUB:
4785 case TargetOpcode::G_STRICT_FSUB: {
4786 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4787 LLT Ty = MRI.getType(Res);
4792 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4793 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4797 MI.eraseFromParent();
4800 case TargetOpcode::G_FMAD:
4802 case TargetOpcode::G_FFLOOR:
4804 case TargetOpcode::G_LROUND:
4805 case TargetOpcode::G_LLROUND: {
4808 LLT SrcTy = MRI.getType(SrcReg);
4809 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4812 MI.eraseFromParent();
4815 case TargetOpcode::G_INTRINSIC_ROUND:
4817 case TargetOpcode::G_FRINT: {
4820 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4823 case TargetOpcode::G_INTRINSIC_LRINT:
4824 case TargetOpcode::G_INTRINSIC_LLRINT: {
4827 LLT SrcTy = MRI.getType(SrcReg);
4829 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4831 MI.eraseFromParent();
4834 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4835 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4836 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4837 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4838 **
MI.memoperands_begin());
4840 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4841 MI.eraseFromParent();
4844 case TargetOpcode::G_LOAD:
4845 case TargetOpcode::G_SEXTLOAD:
4846 case TargetOpcode::G_ZEXTLOAD:
4848 case TargetOpcode::G_STORE:
4850 case TargetOpcode::G_CTLZ_ZERO_POISON:
4851 case TargetOpcode::G_CTTZ_ZERO_POISON:
4852 case TargetOpcode::G_CTLZ:
4853 case TargetOpcode::G_CTTZ:
4854 case TargetOpcode::G_CTPOP:
4855 case TargetOpcode::G_CTLS:
4858 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4860 Register NewRes = MRI.cloneVirtualRegister(Res);
4867 MI.eraseFromParent();
4871 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4872 const LLT CondTy = MRI.getType(CarryOut);
4873 const LLT Ty = MRI.getType(Res);
4875 Register NewRes = MRI.cloneVirtualRegister(Res);
4878 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4884 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4885 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4892 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4897 MI.eraseFromParent();
4901 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4906 MI.eraseFromParent();
4910 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4911 const LLT CondTy = MRI.getType(BorrowOut);
4912 const LLT Ty = MRI.getType(Res);
4915 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4921 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4922 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4929 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4930 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4932 MI.eraseFromParent();
4972 case G_MERGE_VALUES:
4974 case G_UNMERGE_VALUES:
4976 case TargetOpcode::G_SEXT_INREG: {
4977 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4978 int64_t SizeInBits =
MI.getOperand(2).getImm();
4980 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4981 LLT DstTy = MRI.getType(DstReg);
4982 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4985 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4986 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4987 MI.eraseFromParent();
4990 case G_EXTRACT_VECTOR_ELT:
4991 case G_INSERT_VECTOR_ELT:
4993 case G_SHUFFLE_VECTOR:
4995 case G_VECTOR_COMPRESS:
4997 case G_DYN_STACKALLOC:
4999 case G_INSERT_SUBVECTOR: {
5000 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
5001 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
5006 Register Subvector =
MI.getOperand(2).getReg();
5007 auto InsertionPointImm =
MI.getOperand(3).getImm();
5010 LLT DstTy = MRI.getType(Subvector);
5014 bool InsertInLowHalf = InsertionPointImm == 0;
5015 auto Extract =
MIRBuilder.buildExtractSubvector(
5017 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
5019 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
5020 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
5022 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
5023 {LowHalf, HighHalf});
5024 MI.eraseFromParent();
5030 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
5031 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
5037 if (i >= InsertionPointImm &&
5039 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
5047 MI.eraseFromParent();
5051 case G_EXTRACT_SUBVECTOR: {
5054 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5056 LLT SrcTy = MRI.getType(SrcReg);
5057 LLT DstTy = MRI.getType(DstReg);
5059 if (SrcTy.isScalable())
5070 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5071 ExtractionPointImm + i)
5075 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5076 MI.eraseFromParent();
5081 case G_STACKRESTORE:
5091 case G_READ_REGISTER:
5092 case G_WRITE_REGISTER:
5099 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5100 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5106 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5111 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5118 case G_TRUNC_SSAT_S:
5119 case G_TRUNC_USAT_U:
5120 case G_TRUNC_SSAT_U:
5126 bool IsSigned =
MI.getOpcode() == G_ABDS;
5127 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5128 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5129 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5152 case G_MEMCPY_INLINE:
5153 case G_MEMSET_INLINE:
5165 case G_ATOMICRMW_SUB: {
5166 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5167 const LLT ValTy = MRI.getType(Val);
5171 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5172 MI.eraseFromParent();
5200 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5204 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5210 Align StackTypeAlign =
5217 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5218 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5223 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5235 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5238 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5249 "Converting bits to bytes lost precision");
5255 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5256 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5258 if (IdxTy != MRI.getType(Index))
5259 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5264 LLT PtrTy = MRI.getType(VecPtr);
5265 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5273 std::initializer_list<unsigned> NonVecOpIndices) {
5274 if (
MI.getNumMemOperands() != 0)
5282 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5291 if (!Ty.isVector()) {
5297 if (Ty.getNumElements() != NumElts)
5312 assert(Ty.isVector() &&
"Expected vector type");
5314 int NumParts, NumLeftover;
5315 std::tie(NumParts, NumLeftover) =
5318 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5319 for (
int i = 0; i < NumParts; ++i) {
5324 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5333 for (
unsigned i = 0; i <
N; ++i) {
5335 Ops.push_back(
Op.getReg());
5336 else if (
Op.isImm())
5337 Ops.push_back(
Op.getImm());
5338 else if (
Op.isPredicate())
5360 std::initializer_list<unsigned> NonVecOpIndices) {
5362 "Non-compatible opcode or not specified non-vector operands");
5363 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5365 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5366 unsigned NumDefs =
MI.getNumDefs();
5374 for (
unsigned i = 0; i < NumDefs; ++i) {
5375 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5383 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5384 ++UseIdx, ++UseNo) {
5387 MI.getOperand(UseIdx));
5396 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5400 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5402 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5403 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5406 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5407 Uses.push_back(InputOpsPieces[InputNo][i]);
5410 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5411 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5416 for (
unsigned i = 0; i < NumDefs; ++i)
5417 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5419 for (
unsigned i = 0; i < NumDefs; ++i)
5420 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5423 MI.eraseFromParent();
5430 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5432 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5433 unsigned NumDefs =
MI.getNumDefs();
5437 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5442 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5443 UseIdx += 2, ++UseNo) {
5451 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5453 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5454 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5456 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5459 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5460 Phi.addUse(InputOpsPieces[j][i]);
5461 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5471 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5473 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5476 MI.eraseFromParent();
5484 const int NumDst =
MI.getNumOperands() - 1;
5485 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5486 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5487 LLT SrcTy = MRI.getType(SrcReg);
5489 if (TypeIdx != 1 || NarrowTy == DstTy)
5496 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5499 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5513 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5514 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5515 const int PartsPerUnmerge = NumDst / NumUnmerge;
5517 for (
int I = 0;
I != NumUnmerge; ++
I) {
5518 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5520 for (
int J = 0; J != PartsPerUnmerge; ++J)
5521 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5522 MIB.addUse(Unmerge.getReg(
I));
5525 MI.eraseFromParent();
5532 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5536 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5538 if (NarrowTy == SrcTy)
5546 assert(SrcTy.isVector() &&
"Expected vector types");
5548 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5562 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5563 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5564 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5570 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5571 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5572 ++i,
Offset += NumNarrowTyElts) {
5575 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5578 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5579 MI.eraseFromParent();
5583 assert(TypeIdx == 0 &&
"Bad type index");
5584 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5599 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5600 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5602 for (
unsigned i = 0; i < NumParts; ++i) {
5604 for (
unsigned j = 0; j < NumElts; ++j)
5605 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5607 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5610 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5611 MI.eraseFromParent();
5619 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5621 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5623 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5625 InsertVal =
MI.getOperand(2).getReg();
5627 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5628 LLT VecTy = MRI.getType(SrcVec);
5634 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5638 MI.eraseFromParent();
5647 SplitPieces[IdxVal] = InsertVal;
5648 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5650 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5654 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5657 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5658 TargetOpcode::G_ANYEXT);
5662 LLT IdxTy = MRI.getType(Idx);
5663 int64_t PartIdx = IdxVal / NewNumElts;
5665 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5668 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5671 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5672 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5673 VecParts[PartIdx] = InsertPart.getReg(0);
5677 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5679 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5683 MI.eraseFromParent();
5703 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5715 LLT ValTy = MRI.getType(ValReg);
5724 int NumLeftover = -1;
5730 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5732 NumParts = NarrowRegs.
size();
5733 NumLeftover = NarrowLeftoverRegs.
size();
5740 LLT PtrTy = MRI.getType(AddrReg);
5750 auto MMO = LdStMI.
getMMO();
5752 unsigned NumParts,
unsigned Offset) ->
unsigned {
5755 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5757 unsigned ByteOffset =
Offset / 8;
5760 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5767 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5768 ValRegs.push_back(Dst);
5769 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5771 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5780 unsigned HandledOffset =
5781 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5785 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5788 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5789 LeftoverTy, NarrowLeftoverRegs);
5803 switch (
MI.getOpcode()) {
5804 case G_IMPLICIT_DEF:
5820 case G_FCANONICALIZE:
5837 case G_INTRINSIC_LRINT:
5838 case G_INTRINSIC_LLRINT:
5839 case G_INTRINSIC_ROUND:
5840 case G_INTRINSIC_ROUNDEVEN:
5843 case G_INTRINSIC_TRUNC:
5871 case G_FMINNUM_IEEE:
5872 case G_FMAXNUM_IEEE:
5894 case G_CTLZ_ZERO_POISON:
5896 case G_CTTZ_ZERO_POISON:
5913 case G_ADDRSPACE_CAST:
5926 case G_STRICT_FLDEXP:
5928 case G_TRUNC_SSAT_S:
5929 case G_TRUNC_SSAT_U:
5930 case G_TRUNC_USAT_U:
5938 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5943 case G_UNMERGE_VALUES:
5945 case G_BUILD_VECTOR:
5946 assert(TypeIdx == 0 &&
"not a vector type index");
5948 case G_CONCAT_VECTORS:
5952 case G_EXTRACT_SUBVECTOR: {
5954 LLT DstTy = MRI.getType(DstReg);
5956 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5966 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5967 uint64_t RequiredSubvectorIndex =
5971 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5974 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5977 MI.eraseFromParent();
5980 case G_EXTRACT_VECTOR_ELT:
5981 case G_INSERT_VECTOR_ELT:
5990 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5991 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5993 case G_SHUFFLE_VECTOR:
5999 case G_INTRINSIC_FPTRUNC_ROUND:
6009 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
6010 "Not a bitcast operation");
6015 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6017 unsigned NewElemCount =
6020 if (NewElemCount == 1) {
6023 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
6030 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
6039 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
6040 MI.eraseFromParent();
6046 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6050 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6051 MI.getFirst3RegLLTs();
6054 if (DstTy != Src1Ty)
6056 if (DstTy != Src2Ty)
6071 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6087 unsigned InputUsed[2] = {-1U, -1U};
6088 unsigned FirstMaskIdx =
High * NewElts;
6089 bool UseBuildVector =
false;
6090 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6092 int Idx = Mask[FirstMaskIdx + MaskOffset];
6097 if (
Input >= std::size(Inputs)) {
6104 Idx -=
Input * NewElts;
6108 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6109 if (InputUsed[OpNo] ==
Input) {
6112 }
else if (InputUsed[OpNo] == -1U) {
6114 InputUsed[OpNo] =
Input;
6119 if (OpNo >= std::size(InputUsed)) {
6122 UseBuildVector =
true;
6127 Ops.push_back(Idx + OpNo * NewElts);
6130 if (UseBuildVector) {
6135 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6137 int Idx = Mask[FirstMaskIdx + MaskOffset];
6142 if (
Input >= std::size(Inputs)) {
6149 Idx -=
Input * NewElts;
6153 .buildExtractVectorElement(
6154 EltTy, Inputs[
Input],
6160 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6161 }
else if (InputUsed[0] == -1U) {
6163 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6164 }
else if (NewElts == 1) {
6165 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6167 Register Op0 = Inputs[InputUsed[0]];
6171 : Inputs[InputUsed[1]];
6173 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6180 MI.eraseFromParent();
6193 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6199 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6202 const unsigned NumParts =
6204 : SrcTy.getNumElements();
6208 if (DstTy != NarrowTy)
6214 unsigned NumPartsLeft = NumParts;
6215 while (NumPartsLeft > 1) {
6216 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6219 .buildInstr(ScalarOpc, {NarrowTy},
6220 {SplitSrcs[Idx], SplitSrcs[Idx + 1]},
6224 SplitSrcs = PartialResults;
6225 PartialResults.
clear();
6226 NumPartsLeft = SplitSrcs.
size();
6230 MI.eraseFromParent();
6235 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6237 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]},
6241 MI.eraseFromParent();
6245 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6247 .buildInstr(RdxMI.getOpcode(), {DstTy},
6257 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6260 Register Acc = PartialReductions[0];
6261 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6262 if (Part == NumParts - 1) {
6263 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, {Acc, PartialReductions[Part]},
6267 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]},
6272 MI.eraseFromParent();
6278 unsigned int TypeIdx,
6280 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6281 MI.getFirst3RegLLTs();
6282 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6286 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6287 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6288 "Unexpected vecreduce opcode");
6289 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6290 ? TargetOpcode::G_FADD
6291 : TargetOpcode::G_FMUL;
6294 unsigned NumParts = SrcTy.getNumElements();
6297 for (
unsigned i = 0; i < NumParts; i++)
6299 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]},
6304 MI.eraseFromParent();
6311 unsigned ScalarOpc) {
6319 while (SplitSrcs.
size() > 1) {
6321 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6331 SplitSrcs = std::move(PartialRdxs);
6335 MI.getOperand(1).setReg(SplitSrcs[0]);
6342 const LLT HalfTy,
const LLT AmtTy) {
6344 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6345 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6349 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6350 MI.eraseFromParent();
6356 unsigned VTBits = 2 * NVTBits;
6359 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6360 if (Amt.
ugt(VTBits)) {
6362 }
else if (Amt.
ugt(NVTBits)) {
6365 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6366 }
else if (Amt == NVTBits) {
6374 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6377 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6378 if (Amt.
ugt(VTBits)) {
6380 }
else if (Amt.
ugt(NVTBits)) {
6382 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6384 }
else if (Amt == NVTBits) {
6388 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6390 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6392 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6398 if (Amt.
ugt(VTBits)) {
6400 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6401 }
else if (Amt.
ugt(NVTBits)) {
6403 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6405 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6406 }
else if (Amt == NVTBits) {
6409 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6411 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6413 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6415 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6422 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6423 MI.eraseFromParent();
6439 LLT DstTy = MRI.getType(DstReg);
6444 LLT ShiftAmtTy = MRI.getType(Amt);
6446 if (DstEltSize % 2 != 0)
6462 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6473 const unsigned NewBitSize = DstEltSize / 2;
6485 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6487 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6488 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6491 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6492 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6494 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6499 switch (
MI.getOpcode()) {
6500 case TargetOpcode::G_SHL: {
6502 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6504 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6505 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6506 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6509 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6510 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6512 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6514 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6516 ResultRegs[0] =
Lo.getReg(0);
6517 ResultRegs[1] =
Hi.getReg(0);
6520 case TargetOpcode::G_LSHR:
6521 case TargetOpcode::G_ASHR: {
6523 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6525 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6526 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6527 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6531 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6534 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6535 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6537 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6541 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6543 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6545 ResultRegs[0] =
Lo.getReg(0);
6546 ResultRegs[1] =
Hi.getReg(0);
6553 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6554 MI.eraseFromParent();
6563 LLT TargetTy,
LLT ShiftAmtTy) {
6566 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6568 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6569 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6570 const bool NeedsInterWordShift = ShiftBits != 0;
6573 case TargetOpcode::G_SHL: {
6576 if (PartIdx < ShiftWords)
6579 unsigned SrcIdx = PartIdx - ShiftWords;
6580 if (!NeedsInterWordShift)
6581 return SrcParts[SrcIdx];
6586 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6590 return Hi.getReg(0);
6593 case TargetOpcode::G_LSHR: {
6594 unsigned SrcIdx = PartIdx + ShiftWords;
6595 if (SrcIdx >= NumParts)
6597 if (!NeedsInterWordShift)
6598 return SrcParts[SrcIdx];
6602 if (SrcIdx + 1 < NumParts) {
6603 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6607 return Lo.getReg(0);
6610 case TargetOpcode::G_ASHR: {
6612 unsigned SrcIdx = PartIdx + ShiftWords;
6613 if (SrcIdx >= NumParts)
6615 if (!NeedsInterWordShift)
6616 return SrcParts[SrcIdx];
6621 (SrcIdx == NumParts - 1)
6625 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6647 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6648 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6653 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6662 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6663 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6665 auto IsZeroBitShift =
6673 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6674 : TargetOpcode::G_SHL;
6677 auto TargetBitsConst =
6679 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6684 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6689 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6691 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6695 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6708 LLT DstTy = MRI.getType(DstReg);
6712 const unsigned NumParts = DstBits / TargetBits;
6714 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6724 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6725 MI.eraseFromParent();
6730 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6731 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6737 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6741 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6744 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6745 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6749 for (
unsigned I = 0;
I < NumParts; ++
I)
6751 Params, TargetTy, ShiftAmtTy);
6753 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6754 MI.eraseFromParent();
6763 LLT DstTy = MRI.getType(DstReg);
6764 LLT ShiftAmtTy = MRI.getType(AmtReg);
6768 const unsigned NumParts = DstBits / TargetBits;
6770 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6787 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6799 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6800 auto TargetBitsLog2Const =
6801 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6802 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6805 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6807 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6815 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6816 auto TargetBitsMinusOneConst =
6817 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6819 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6820 TargetBitsMinusOneConst)
6823 FillValue = ZeroReg;
6831 for (
unsigned I = 0;
I < NumParts; ++
I) {
6833 Register InBoundsResult = FillValue;
6843 for (
unsigned K = 0;
K < NumParts; ++
K) {
6844 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy,
K);
6846 WordShift, WordShiftKConst);
6858 switch (
MI.getOpcode()) {
6859 case TargetOpcode::G_SHL:
6860 MainSrcIdx = (int)
I - (
int)
K;
6861 CarrySrcIdx = MainSrcIdx - 1;
6863 case TargetOpcode::G_LSHR:
6864 case TargetOpcode::G_ASHR:
6865 MainSrcIdx = (int)
I + (
int)
K;
6866 CarrySrcIdx = MainSrcIdx + 1;
6874 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6875 Register MainOp = SrcParts[MainSrcIdx];
6879 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6880 CarryOp = SrcParts[CarrySrcIdx];
6881 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6882 CarrySrcIdx >= (
int)NumParts)
6883 CarryOp = FillValue;
6889 ResultForK = FillValue;
6895 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6902 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6906 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6907 MI.eraseFromParent();
6914 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6917 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6932 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6937 "getNeutralElementForVecReduce called with invalid opcode!");
6938 case TargetOpcode::G_VECREDUCE_ADD:
6939 case TargetOpcode::G_VECREDUCE_OR:
6940 case TargetOpcode::G_VECREDUCE_XOR:
6941 case TargetOpcode::G_VECREDUCE_UMAX:
6943 case TargetOpcode::G_VECREDUCE_MUL:
6945 case TargetOpcode::G_VECREDUCE_AND:
6946 case TargetOpcode::G_VECREDUCE_UMIN:
6949 case TargetOpcode::G_VECREDUCE_SMAX:
6952 case TargetOpcode::G_VECREDUCE_SMIN:
6955 case TargetOpcode::G_VECREDUCE_FADD:
6957 case TargetOpcode::G_VECREDUCE_FMUL:
6959 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6960 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6961 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6962 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6970 unsigned Opc =
MI.getOpcode();
6972 case TargetOpcode::G_IMPLICIT_DEF:
6973 case TargetOpcode::G_LOAD: {
6981 case TargetOpcode::G_STORE:
6988 case TargetOpcode::G_AND:
6989 case TargetOpcode::G_OR:
6990 case TargetOpcode::G_XOR:
6991 case TargetOpcode::G_ADD:
6992 case TargetOpcode::G_SUB:
6993 case TargetOpcode::G_MUL:
6994 case TargetOpcode::G_FADD:
6995 case TargetOpcode::G_FSUB:
6996 case TargetOpcode::G_FMUL:
6997 case TargetOpcode::G_FDIV:
6998 case TargetOpcode::G_FCOPYSIGN:
6999 case TargetOpcode::G_UADDSAT:
7000 case TargetOpcode::G_USUBSAT:
7001 case TargetOpcode::G_SADDSAT:
7002 case TargetOpcode::G_SSUBSAT:
7003 case TargetOpcode::G_SMIN:
7004 case TargetOpcode::G_SMAX:
7005 case TargetOpcode::G_UMIN:
7006 case TargetOpcode::G_UMAX:
7007 case TargetOpcode::G_FMINNUM:
7008 case TargetOpcode::G_FMAXNUM:
7009 case TargetOpcode::G_FMINNUM_IEEE:
7010 case TargetOpcode::G_FMAXNUM_IEEE:
7011 case TargetOpcode::G_FMINIMUM:
7012 case TargetOpcode::G_FMAXIMUM:
7013 case TargetOpcode::G_FMINIMUMNUM:
7014 case TargetOpcode::G_FMAXIMUMNUM:
7015 case TargetOpcode::G_STRICT_FADD:
7016 case TargetOpcode::G_STRICT_FSUB:
7017 case TargetOpcode::G_STRICT_FMUL: {
7025 case TargetOpcode::G_SHL:
7026 case TargetOpcode::G_ASHR:
7027 case TargetOpcode::G_LSHR: {
7033 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
7039 case TargetOpcode::G_FMA:
7040 case TargetOpcode::G_STRICT_FMA:
7041 case TargetOpcode::G_FSHR:
7042 case TargetOpcode::G_FSHL: {
7051 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
7052 case TargetOpcode::G_EXTRACT:
7059 case TargetOpcode::G_INSERT:
7060 case TargetOpcode::G_INSERT_VECTOR_ELT:
7061 case TargetOpcode::G_FREEZE:
7062 case TargetOpcode::G_FNEG:
7063 case TargetOpcode::G_FABS:
7064 case TargetOpcode::G_FSQRT:
7065 case TargetOpcode::G_FCEIL:
7066 case TargetOpcode::G_FFLOOR:
7067 case TargetOpcode::G_FNEARBYINT:
7068 case TargetOpcode::G_FRINT:
7069 case TargetOpcode::G_INTRINSIC_ROUND:
7070 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7071 case TargetOpcode::G_INTRINSIC_TRUNC:
7072 case TargetOpcode::G_BITREVERSE:
7073 case TargetOpcode::G_BSWAP:
7074 case TargetOpcode::G_FCANONICALIZE:
7075 case TargetOpcode::G_SEXT_INREG:
7076 case TargetOpcode::G_ABS:
7077 case TargetOpcode::G_CTLZ:
7078 case TargetOpcode::G_CTPOP:
7086 case TargetOpcode::G_SELECT: {
7087 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7089 if (!CondTy.isScalar() ||
7095 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7097 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7102 if (CondTy.isVector())
7112 case TargetOpcode::G_UNMERGE_VALUES:
7114 case TargetOpcode::G_PHI:
7116 case TargetOpcode::G_SHUFFLE_VECTOR:
7118 case TargetOpcode::G_BUILD_VECTOR: {
7120 for (
auto Op :
MI.uses()) {
7128 MIRBuilder.buildDeleteTrailingVectorElements(
7129 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7130 MI.eraseFromParent();
7133 case TargetOpcode::G_SEXT:
7134 case TargetOpcode::G_ZEXT:
7135 case TargetOpcode::G_ANYEXT:
7136 case TargetOpcode::G_TRUNC:
7137 case TargetOpcode::G_FPTRUNC:
7138 case TargetOpcode::G_FPEXT:
7139 case TargetOpcode::G_FPTOSI:
7140 case TargetOpcode::G_FPTOUI:
7141 case TargetOpcode::G_FPTOSI_SAT:
7142 case TargetOpcode::G_FPTOUI_SAT:
7143 case TargetOpcode::G_SITOFP:
7144 case TargetOpcode::G_UITOFP:
7145 case TargetOpcode::G_TRUNC_SSAT_S:
7146 case TargetOpcode::G_TRUNC_SSAT_U:
7147 case TargetOpcode::G_TRUNC_USAT_U: {
7154 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7157 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7165 case TargetOpcode::G_ICMP:
7166 case TargetOpcode::G_FCMP: {
7174 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7179 case TargetOpcode::G_BITCAST: {
7183 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7184 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7200 case TargetOpcode::G_VECREDUCE_FADD:
7201 case TargetOpcode::G_VECREDUCE_FMUL:
7202 case TargetOpcode::G_VECREDUCE_ADD:
7203 case TargetOpcode::G_VECREDUCE_MUL:
7204 case TargetOpcode::G_VECREDUCE_AND:
7205 case TargetOpcode::G_VECREDUCE_OR:
7206 case TargetOpcode::G_VECREDUCE_XOR:
7207 case TargetOpcode::G_VECREDUCE_SMAX:
7208 case TargetOpcode::G_VECREDUCE_SMIN:
7209 case TargetOpcode::G_VECREDUCE_UMAX:
7210 case TargetOpcode::G_VECREDUCE_UMIN: {
7211 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7213 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7214 auto NeutralElement = getNeutralElementForVecReduce(
7220 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7221 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7222 NeutralElement, Idx);
7226 MO.
setReg(NewVec.getReg(0));
7238 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7240 unsigned MaskNumElts = Mask.size();
7241 unsigned SrcNumElts = SrcTy.getNumElements();
7244 if (MaskNumElts == SrcNumElts)
7247 if (MaskNumElts < SrcNumElts) {
7255 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7256 MI.getOperand(1).getReg(),
7257 MI.getOperand(2).getReg(), NewMask);
7258 MI.eraseFromParent();
7263 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7264 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7273 MOps1[0] =
MI.getOperand(1).getReg();
7274 MOps2[0] =
MI.getOperand(2).getReg();
7276 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7277 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7281 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7283 if (Idx >=
static_cast<int>(SrcNumElts))
7284 Idx += PaddedMaskNumElts - SrcNumElts;
7289 if (MaskNumElts != PaddedMaskNumElts) {
7291 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7294 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7296 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7301 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7304 MI.eraseFromParent();
7310 unsigned int TypeIdx,
LLT MoreTy) {
7311 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7313 unsigned NumElts = DstTy.getNumElements();
7316 if (DstTy.isVector() && Src1Ty.isVector() &&
7317 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7325 if (DstTy != Src1Ty || DstTy != Src2Ty)
7333 for (
unsigned I = 0;
I != NumElts; ++
I) {
7335 if (Idx <
static_cast<int>(NumElts))
7338 NewMask[
I] = Idx - NumElts + WidenNumElts;
7342 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7343 MI.getOperand(1).getReg(),
7344 MI.getOperand(2).getReg(), NewMask);
7345 MI.eraseFromParent();
7354 unsigned SrcParts = Src1Regs.
size();
7355 unsigned DstParts = DstRegs.
size();
7357 unsigned DstIdx = 0;
7359 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7360 DstRegs[DstIdx] = FactorSum;
7365 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7367 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7368 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7370 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7376 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7377 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7378 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7379 unsigned i = RevI - 1;
7381 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7391 if (DstIdx != DstParts - 1) {
7392 MachineInstrBuilder Uaddo =
7393 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7394 FactorSum = Uaddo.
getReg(0);
7395 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7396 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7397 MachineInstrBuilder Uaddo =
7398 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7399 FactorSum = Uaddo.
getReg(0);
7400 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7401 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7405 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7406 for (
unsigned i = 2; i < Factors.
size(); ++i)
7407 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7410 CarrySumPrevDstIdx = CarrySum;
7411 DstRegs[DstIdx] = FactorSum;
7423 LLT DstType = MRI.getType(DstReg);
7425 if (DstType.isVector())
7428 unsigned Opcode =
MI.getOpcode();
7429 unsigned OpO, OpE, OpF;
7431 case TargetOpcode::G_SADDO:
7432 case TargetOpcode::G_SADDE:
7433 case TargetOpcode::G_UADDO:
7434 case TargetOpcode::G_UADDE:
7435 case TargetOpcode::G_ADD:
7436 OpO = TargetOpcode::G_UADDO;
7437 OpE = TargetOpcode::G_UADDE;
7438 OpF = TargetOpcode::G_UADDE;
7439 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7440 OpF = TargetOpcode::G_SADDE;
7442 case TargetOpcode::G_SSUBO:
7443 case TargetOpcode::G_SSUBE:
7444 case TargetOpcode::G_USUBO:
7445 case TargetOpcode::G_USUBE:
7446 case TargetOpcode::G_SUB:
7447 OpO = TargetOpcode::G_USUBO;
7448 OpE = TargetOpcode::G_USUBE;
7449 OpF = TargetOpcode::G_USUBE;
7450 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7451 OpF = TargetOpcode::G_SSUBE;
7458 unsigned NumDefs =
MI.getNumExplicitDefs();
7459 Register Src1 =
MI.getOperand(NumDefs).getReg();
7460 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7463 CarryDst =
MI.getOperand(1).getReg();
7464 if (
MI.getNumOperands() == NumDefs + 3)
7465 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7467 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7468 LLT LeftoverTy, DummyTy;
7470 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7475 int NarrowParts = Src1Regs.
size();
7476 Src1Regs.
append(Src1Left);
7477 Src2Regs.
append(Src2Left);
7480 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7482 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7485 if (i == e - 1 && CarryDst)
7486 CarryOut = CarryDst;
7488 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7491 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7492 {Src1Regs[i], Src2Regs[i]});
7493 }
else if (i == e - 1) {
7494 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7495 {Src1Regs[i], Src2Regs[i], CarryIn});
7497 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7498 {Src1Regs[i], Src2Regs[i], CarryIn});
7504 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7505 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7506 ArrayRef(DstRegs).drop_front(NarrowParts));
7508 MI.eraseFromParent();
7514 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7516 LLT Ty = MRI.getType(DstReg);
7520 unsigned Size = Ty.getSizeInBits();
7522 if (
Size % NarrowSize != 0)
7525 unsigned NumParts =
Size / NarrowSize;
7526 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7527 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7533 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7537 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7538 MI.eraseFromParent();
7548 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7551 LLT SrcTy = MRI.getType(Src);
7563 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7576 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7579 if (SizeOp1 % NarrowSize != 0)
7581 int NumParts = SizeOp1 / NarrowSize;
7584 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7588 uint64_t OpStart =
MI.getOperand(2).getImm();
7589 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7590 for (
int i = 0; i < NumParts; ++i) {
7591 unsigned SrcStart = i * NarrowSize;
7593 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7596 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7604 int64_t ExtractOffset;
7606 if (OpStart < SrcStart) {
7608 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7610 ExtractOffset = OpStart - SrcStart;
7611 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7615 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7617 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7618 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7625 if (MRI.getType(DstReg).isVector())
7626 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7627 else if (DstRegs.
size() > 1)
7628 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7631 MI.eraseFromParent();
7643 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7645 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7648 SrcRegs.
append(LeftoverRegs);
7652 uint64_t OpStart =
MI.getOperand(3).getImm();
7653 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7654 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7655 unsigned DstStart =
I * NarrowSize;
7657 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7665 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7667 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7671 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7679 int64_t ExtractOffset, InsertOffset;
7681 if (OpStart < DstStart) {
7683 ExtractOffset = DstStart - OpStart;
7684 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7686 InsertOffset = OpStart - DstStart;
7688 SegSize = std::min(NarrowSize - InsertOffset, OpSize);
7692 if (ExtractOffset != 0 || SegSize != OpSize) {
7694 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7695 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7698 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7699 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7703 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7707 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7710 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7712 MI.eraseFromParent();
7720 LLT DstTy = MRI.getType(DstReg);
7722 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7728 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7729 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7733 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7734 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7737 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7738 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7739 {Src0Regs[I], Src1Regs[I]});
7743 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7746 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7747 DstLeftoverRegs.
push_back(Inst.getReg(0));
7750 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7751 LeftoverTy, DstLeftoverRegs);
7753 MI.eraseFromParent();
7763 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7765 LLT DstTy = MRI.getType(DstReg);
7770 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7771 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7772 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7774 MI.eraseFromParent();
7784 Register CondReg =
MI.getOperand(1).getReg();
7785 LLT CondTy = MRI.getType(CondReg);
7786 if (CondTy.isVector())
7790 LLT DstTy = MRI.getType(DstReg);
7796 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7797 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7801 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7802 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7805 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7807 CondReg, Src1Regs[
I], Src2Regs[
I]);
7811 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7813 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7817 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7818 LeftoverTy, DstLeftoverRegs);
7820 MI.eraseFromParent();
7830 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7833 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7834 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7837 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7839 auto C_0 =
B.buildConstant(NarrowTy, 0);
7841 UnmergeSrc.getReg(1), C_0);
7842 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7843 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7844 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7845 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7846 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7847 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7849 MI.eraseFromParent();
7862 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7865 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7866 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7869 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7871 auto C_0 =
B.buildConstant(NarrowTy, 0);
7873 UnmergeSrc.getReg(0), C_0);
7874 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7875 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7876 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7877 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7878 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7879 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7881 MI.eraseFromParent();
7894 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7897 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7902 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7906 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7907 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7915 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7916 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7919 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7920 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7922 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7924 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7926 MI.eraseFromParent();
7936 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7939 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7940 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7942 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7943 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7944 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7946 MI.eraseFromParent();
7961 LLT ExpTy = MRI.getType(ExpReg);
7966 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7967 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7968 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7969 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7971 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7973 MI.getOperand(2).setReg(Trunc.getReg(0));
7980 unsigned Opc =
MI.getOpcode();
7983 auto QAction = LI.getAction(Q).Action;
7989 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7992 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7996 case TargetOpcode::G_CTLZ: {
7997 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7998 unsigned Len = SrcTy.getScalarSizeInBits();
8000 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
8002 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
8003 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
8006 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8007 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
8008 MI.eraseFromParent();
8024 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
8025 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
8028 Op = MIBOp.getReg(0);
8033 MI.eraseFromParent();
8036 case TargetOpcode::G_CTTZ_ZERO_POISON: {
8039 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
8043 case TargetOpcode::G_CTTZ: {
8044 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8046 unsigned Len = SrcTy.getScalarSizeInBits();
8047 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
8050 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
8051 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
8054 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8055 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
8056 MI.eraseFromParent();
8063 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8064 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8066 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8067 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8068 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8069 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8072 MI.eraseFromParent();
8076 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8077 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8081 case TargetOpcode::G_CTPOP: {
8083 LLT Ty = MRI.getType(SrcReg);
8084 unsigned Size = Ty.getScalarSizeInBits();
8096 auto C_1 =
B.buildConstant(Ty, 1);
8097 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8099 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8100 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8101 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8105 auto C_2 =
B.buildConstant(Ty, 2);
8106 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8108 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8109 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8110 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8111 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8118 auto C_4 =
B.buildConstant(Ty, 4);
8119 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8120 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8122 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8123 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8125 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8128 if (
Size == 16 && !Ty.isVector()) {
8130 auto C_8 =
B.buildConstant(Ty, 8);
8131 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8132 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8133 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8134 MI.eraseFromParent();
8143 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8145 auto IsMulSupported = [
this](
const LLT Ty) {
8146 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8149 if (IsMulSupported(Ty)) {
8150 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8151 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8153 auto ResTmp = B8Count;
8154 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8155 auto ShiftC =
B.buildConstant(Ty, Shift);
8156 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8157 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8159 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8161 MI.eraseFromParent();
8164 case TargetOpcode::G_CTLS: {
8165 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8169 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8170 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8172 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8178 MI.eraseFromParent();
8199 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8200 LLT Ty = MRI.getType(Dst);
8201 LLT ShTy = MRI.getType(Z);
8208 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8209 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8214 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8215 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8219 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8232 MI.eraseFromParent();
8238 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8239 LLT Ty = MRI.getType(Dst);
8240 LLT ShTy = MRI.getType(Z);
8243 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8253 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8254 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8255 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8256 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8257 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8261 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8264 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8267 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8269 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8270 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8271 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8274 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8276 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8278 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8281 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8282 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8287 MI.eraseFromParent();
8298 LLT Ty = MRI.getType(Dst);
8299 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8301 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8302 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8305 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8306 return lowerFunnelShiftAsShifts(
MI);
8310 if (Result == UnableToLegalize)
8311 return lowerFunnelShiftAsShifts(
MI);
8316 auto [Dst, Src] =
MI.getFirst2Regs();
8317 LLT DstTy = MRI.getType(Dst);
8318 LLT SrcTy = MRI.getType(Src);
8322 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8330 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8334 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8338 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8343 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8344 {UnmergeSrc.getReg(0)});
8345 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8346 {UnmergeSrc.getReg(1)});
8349 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8351 MI.eraseFromParent();
8368 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8372 LLT DstTy = MRI.getType(DstReg);
8373 LLT SrcTy = MRI.getType(SrcReg);
8381 SrcTy.getElementCount().divideCoefficientBy(2));
8394 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8406 MI.eraseFromParent();
8415 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8416 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8417 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8418 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8419 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8420 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8421 MI.eraseFromParent();
8426 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8428 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8429 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8434 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8435 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8437 return lowerRotateWithReverseRotate(
MI);
8440 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8441 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8442 bool IsFShLegal =
false;
8443 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8444 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8448 MI.eraseFromParent();
8453 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8456 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8461 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8462 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8463 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8469 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8470 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8472 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8478 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8479 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8481 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8483 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8488 MI.eraseFromParent();
8496 auto [Dst, Src] =
MI.getFirst2Regs();
8501 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8514 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8516 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8521 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8523 MI.eraseFromParent();
8531 auto [Dst, Src] =
MI.getFirst2Regs();
8535 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8546 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8547 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8549 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8556 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8557 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8558 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8560 MI.eraseFromParent();
8571 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8572 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8578 MI.eraseFromParent();
8583 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8589 MI.eraseFromParent();
8593 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8613 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8623 MI.eraseFromParent();
8627 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8633 if (DstTy.getScalarSizeInBits() == 32) {
8640 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8641 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8643 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8650 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8651 MI.eraseFromParent();
8659 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8663 if (SrcTy !=
S64 && SrcTy !=
S32)
8665 if (DstTy !=
S32 && DstTy !=
S64)
8692 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8694 MI.eraseFromParent();
8699 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8704 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8711 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8713 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8714 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8716 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8717 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8719 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8721 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8722 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8723 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8726 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8727 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8728 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8730 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask,
K);
8733 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8738 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8739 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8745 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8747 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8748 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8750 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8755 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8756 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8758 MI.eraseFromParent();
8764 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8766 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8767 unsigned SatWidth = DstTy.getScalarSizeInBits();
8771 APInt MinInt, MaxInt;
8794 if (AreExactFloatBounds) {
8796 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8799 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8801 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8810 MI.eraseFromParent();
8815 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8820 MI.eraseFromParent();
8827 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8835 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8845 MI.eraseFromParent();
8851 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8855 MI.eraseFromParent();
8862 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8863 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8864 "Only G_FPEXT and G_FPTRUNC are expected");
8866 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8871 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8873 StoreOpc = TargetOpcode::G_STORE;
8874 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8877 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8878 LoadOpc = TargetOpcode::G_LOAD;
8887 StackTy, StackTyAlign);
8888 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8891 StackTy, StackTyAlign);
8892 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8894 MI.eraseFromParent();
8902 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8903 assert(SrcTy.getScalarType().isBFloat16() &&
8904 "expected a bf16 source for bf16 fpext lowering");
8915 if (DstTy.getScalarType().isFloat32())
8920 MI.eraseFromParent();
8925 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8926 if (SrcTy.getScalarType().isBFloat16() &&
8927 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8939 auto [Dst, Src] =
MI.getFirst2Regs();
8943 if (MRI.getType(Src).isVector())
8947 unsigned Flags =
MI.getFlags();
8950 MI.eraseFromParent();
8954 const unsigned ExpMask = 0x7ff;
8955 const unsigned ExpBiasf64 = 1023;
8956 const unsigned ExpBiasf16 = 15;
8958 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8968 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8975 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8977 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8979 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8983 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8985 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8987 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8988 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8996 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8997 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
9008 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9019 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9035 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9045 MI.eraseFromParent();
9052 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9060 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9086 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9088 MI.eraseFromParent();
9097 LLT OperandTy = MRI.getType(
Op);
9107 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9109 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9110 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9111 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9112 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9113 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9121 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9124 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9126 AbsWide, AbsNarrowAsWide);
9130 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9131 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9133 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9134 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9140 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9146 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9147 MI.eraseFromParent();
9153 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9154 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9157 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9160 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9167 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9168 LLT Ty = MRI.getType(Dst);
9170 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9171 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9172 MI.eraseFromParent();
9177 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9178 LLT Ty = MRI.getType(Src);
9179 auto Flags =
MI.getFlags();
9187 FracToUse = FracPart.getReg(0);
9189 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9193 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9195 FracToUse =
Select.getReg(0);
9198 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9201 MI.eraseFromParent();
9207 case TargetOpcode::G_SMIN:
9209 case TargetOpcode::G_SMAX:
9211 case TargetOpcode::G_UMIN:
9213 case TargetOpcode::G_UMAX:
9221 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9226 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9227 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9229 MI.eraseFromParent();
9238 LLT DstTy = MRI.getType(Dst);
9239 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9249 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9250 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9252 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9255 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9256 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9257 if (TLI.preferSelectsOverBooleanArithmetic(
9260 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9261 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9263 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9264 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9270 unsigned BoolExtOp =
9272 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9273 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9277 MI.eraseFromParent();
9283 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9284 const int Src0Size = Src0Ty.getScalarSizeInBits();
9285 const int Src1Size = Src1Ty.getScalarSizeInBits();
9295 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9296 Src0Ty.getScalarType().isInteger()))
9297 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9299 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9300 Src1Ty.getScalarType().isInteger()))
9301 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9306 auto NotSignBitMask =
MIRBuilder.buildConstant(
9310 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9312 if (Src0Ty == Src1Ty) {
9313 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9314 }
else if (Src0Size > Src1Size) {
9315 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9316 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9317 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9318 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9320 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9321 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9322 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9323 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9329 unsigned Flags =
MI.getFlags();
9334 if (DstTy == DstIntTy)
9335 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9341 MI.eraseFromParent();
9352 switch (
MI.getOpcode()) {
9353 case TargetOpcode::G_FMINNUM:
9354 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9356 case TargetOpcode::G_FMINIMUMNUM:
9357 NewOp = TargetOpcode::G_FMINNUM;
9359 case TargetOpcode::G_FMAXNUM:
9360 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9362 case TargetOpcode::G_FMAXIMUMNUM:
9363 NewOp = TargetOpcode::G_FMAXNUM;
9369 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9370 LLT Ty = MRI.getType(Dst);
9379 if (!VT->isKnownNeverSNaN(Src0))
9380 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9382 if (!VT->isKnownNeverSNaN(Src1))
9383 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9388 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9389 MI.eraseFromParent();
9395 unsigned Opc =
MI.getOpcode();
9396 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9397 LLT Ty = MRI.getType(Dst);
9400 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9402 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9403 unsigned OpcNonIeee =
9404 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9405 bool MinMaxMustRespectOrderedZero =
false;
9409 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9411 MinMaxMustRespectOrderedZero =
true;
9412 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9417 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9422 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9425 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9429 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9431 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9441 const unsigned Flags =
MI.getFlags();
9447 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9449 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9451 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9453 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9455 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9460 MI.eraseFromParent();
9467 LLT Ty = MRI.getType(DstReg);
9468 unsigned Flags =
MI.getFlags();
9473 MI.eraseFromParent();
9479 auto [DstReg,
X] =
MI.getFirst2Regs();
9480 const unsigned Flags =
MI.getFlags();
9481 const LLT Ty = MRI.getType(DstReg);
9493 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9495 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9500 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9501 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9502 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9503 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9505 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9507 MI.eraseFromParent();
9512 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9513 unsigned Flags =
MI.getFlags();
9514 LLT Ty = MRI.getType(DstReg);
9521 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9522 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9525 SrcReg, Zero, Flags);
9527 SrcReg, Trunc, Flags);
9531 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9532 MI.eraseFromParent();
9538 const unsigned NumOps =
MI.getNumOperands();
9539 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9540 unsigned PartSize = Src0Ty.getSizeInBits();
9545 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9546 const unsigned Offset = (
I - 1) * PartSize;
9549 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9552 MRI.createGenericVirtualRegister(WideTy);
9555 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9556 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9557 ResultReg = NextResult;
9560 if (DstTy.isPointer()) {
9561 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9562 DstTy.getAddressSpace())) {
9568 }
else if (WideTy != DstTy) {
9572 MI.eraseFromParent();
9578 const unsigned NumDst =
MI.getNumOperands() - 1;
9579 Register SrcReg =
MI.getOperand(NumDst).getReg();
9580 Register Dst0Reg =
MI.getOperand(0).getReg();
9581 LLT DstTy = MRI.getType(Dst0Reg);
9590 LLT IntTy = MRI.getType(SrcReg);
9595 unsigned Offset = DstSize;
9596 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9598 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9602 MI.eraseFromParent();
9621 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9622 InsertVal =
MI.getOperand(2).getReg();
9624 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9626 LLT VecTy = MRI.getType(SrcVec);
9636 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9637 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9639 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9642 MI.eraseFromParent();
9647 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9658 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9665 int64_t
Offset = IdxVal * EltBytes;
9676 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9679 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9681 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9684 MI.eraseFromParent();
9690 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9691 MI.getFirst3RegLLTs();
9701 for (
int Idx : Mask) {
9703 if (!
Undef.isValid())
9709 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9711 int NumElts = Src0Ty.getNumElements();
9712 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9713 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9714 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9716 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9718 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9723 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9724 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9725 MI.eraseFromParent();
9731 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9732 MI.getFirst4RegLLTs();
9734 if (VecTy.isScalableVector())
9750 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9755 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9758 std::optional<APInt> PassthruSplatVal =
9761 if (PassthruSplatVal.has_value()) {
9763 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9764 }
else if (HasPassthru) {
9765 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9766 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9772 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9776 unsigned NumElmts = VecTy.getNumElements();
9777 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9779 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9782 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9785 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9790 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9792 if (HasPassthru &&
I == NumElmts - 1) {
9795 auto AllLanesSelected =
MIRBuilder.buildICmp(
9797 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9798 {OutPos, EndOfVector});
9802 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9804 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9809 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9811 MI.eraseFromParent();
9828 if (Alignment >
Align(1)) {
9829 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9840 const auto &MF = *
MI.getMF();
9846 Register AllocSize =
MI.getOperand(1).getReg();
9849 LLT PtrTy = MRI.getType(Dst);
9850 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9857 MI.eraseFromParent();
9863 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9868 MI.eraseFromParent();
9874 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9879 MI.eraseFromParent();
9885 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9886 unsigned Offset =
MI.getOperand(2).getImm();
9889 if (SrcTy.isVector()) {
9890 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9891 unsigned DstSize = DstTy.getSizeInBits();
9893 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9894 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9896 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9900 for (
unsigned Idx =
Offset / SrcEltSize;
9901 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9902 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9904 if (SubVectorElts.
size() == 1)
9905 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9907 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9909 MI.eraseFromParent();
9915 if ((SrcTy.isPointer() &&
9916 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9917 (DstTy.isPointer() &&
9918 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9919 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9923 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9924 (SrcTy.isScalar() || SrcTy.isPointer() ||
9925 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9926 LLT SrcIntTy = SrcTy;
9927 if (!SrcTy.isScalar()) {
9929 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9933 if (DstTy.isPointer())
9935 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9941 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9945 if (DstTy.isPointer())
9948 MI.eraseFromParent();
9956 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9957 uint64_t
Offset =
MI.getOperand(3).getImm();
9959 LLT DstTy = MRI.getType(Src);
9960 LLT InsertTy = MRI.getType(InsertSrc);
9963 bool IsNonIntegralInsert =
9973 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9974 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9981 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9983 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9987 for (; Idx <
Offset / EltSize; ++Idx) {
9988 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9993 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9994 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9996 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
10000 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
10002 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
10009 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10012 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
10013 MI.eraseFromParent();
10022 if (IsNonIntegralDst || IsNonIntegralInsert) {
10023 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10027 LLT IntDstTy = DstTy;
10031 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
10036 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
10042 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10048 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10049 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10050 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10053 MI.eraseFromParent();
10059 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10060 MI.getFirst4RegLLTs();
10061 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10064 LLT BoolTy = Dst1Ty;
10066 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10075 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10081 auto ResultLowerThanLHS =
10085 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10089 auto LHSLessThanRHS =
10091 auto ResultNegative =
10093 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10097 MI.eraseFromParent();
10103 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10104 const LLT Ty = MRI.getType(Res);
10107 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10108 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10109 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10113 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10114 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10117 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10120 MI.eraseFromParent();
10125 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10126 const LLT Ty = MRI.getType(Res);
10129 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10130 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10131 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10135 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10136 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10138 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10141 MI.eraseFromParent();
10147 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10148 LLT Ty = MRI.getType(Res);
10152 switch (
MI.getOpcode()) {
10155 case TargetOpcode::G_UADDSAT:
10158 BaseOp = TargetOpcode::G_ADD;
10160 case TargetOpcode::G_SADDSAT:
10163 BaseOp = TargetOpcode::G_ADD;
10165 case TargetOpcode::G_USUBSAT:
10168 BaseOp = TargetOpcode::G_SUB;
10170 case TargetOpcode::G_SSUBSAT:
10173 BaseOp = TargetOpcode::G_SUB;
10188 uint64_t NumBits = Ty.getScalarSizeInBits();
10195 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10199 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10207 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10212 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10213 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10216 MI.eraseFromParent();
10222 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10223 LLT Ty = MRI.getType(Res);
10227 unsigned OverflowOp;
10228 switch (
MI.getOpcode()) {
10231 case TargetOpcode::G_UADDSAT:
10234 OverflowOp = TargetOpcode::G_UADDO;
10236 case TargetOpcode::G_SADDSAT:
10239 OverflowOp = TargetOpcode::G_SADDO;
10241 case TargetOpcode::G_USUBSAT:
10244 OverflowOp = TargetOpcode::G_USUBO;
10246 case TargetOpcode::G_SSUBSAT:
10249 OverflowOp = TargetOpcode::G_SSUBO;
10254 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10255 Register Tmp = OverflowRes.getReg(0);
10256 Register Ov = OverflowRes.getReg(1);
10265 uint64_t NumBits = Ty.getScalarSizeInBits();
10266 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10267 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10270 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10278 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10280 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10282 MI.eraseFromParent();
10288 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10289 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10290 "Expected shlsat opcode!");
10291 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10292 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10293 LLT Ty = MRI.getType(Res);
10297 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10298 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10307 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10312 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10314 MI.eraseFromParent();
10320 unsigned Opc =
MI.getOpcode();
10321 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10322 unsigned DstSize = DstTy.getScalarSizeInBits();
10323 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10325 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10328 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10331 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10332 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10335 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10336 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10339 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10341 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10347 MI.eraseFromParent();
10352 auto [Dst, Src] =
MI.getFirst2Regs();
10353 const LLT Ty = MRI.getType(Src);
10354 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10355 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10358 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10359 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10360 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10361 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10364 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10367 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10368 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10370 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10371 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10372 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10374 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10375 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10376 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10378 Res.getInstr()->getOperand(0).setReg(Dst);
10380 MI.eraseFromParent();
10387 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10390 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10391 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10392 return B.buildOr(Dst,
LHS,
RHS);
10397 auto [Dst, Src] =
MI.getFirst2Regs();
10398 const LLT SrcTy = MRI.getType(Src);
10399 unsigned Size = SrcTy.getScalarSizeInBits();
10400 unsigned VSize = SrcTy.getSizeInBits();
10403 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10404 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10405 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10406 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10411 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10412 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10413 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10417 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10440 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10444 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10447 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10451 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10455 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10460 MI.eraseFromParent();
10468 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10469 int NameOpIdx = IsRead ? 1 : 0;
10470 int ValRegIndex = IsRead ? 0 : 1;
10472 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10473 const LLT Ty = MRI.getType(ValReg);
10475 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10482 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10483 Fn,
MI.getDebugLoc()));
10487 MI.eraseFromParent();
10496 MI.eraseFromParent();
10502 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10503 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10504 Register Result =
MI.getOperand(0).getReg();
10505 LLT OrigTy = MRI.getType(Result);
10509 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10510 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10512 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10514 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10515 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10518 MI.eraseFromParent();
10524 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10529 MI.eraseFromParent();
10534 MI.eraseFromParent();
10541 unsigned BitSize = SrcTy.getScalarSizeInBits();
10545 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10552 APInt ExpMask = Inf;
10554 APInt QNaNBitMask =
10558 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10559 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10560 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10561 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10562 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10564 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10568 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10570 LLT DstTyCopy = DstTy;
10572 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10600 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10603 Mask &= ~PartialCheck;
10612 else if (PartialCheck ==
fcZero)
10624 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10625 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10626 auto SubnormalRes =
10628 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10630 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10631 appendToRes(SubnormalRes);
10638 else if (PartialCheck ==
fcInf)
10643 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10650 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10651 if (PartialCheck ==
fcNan) {
10655 }
else if (PartialCheck ==
fcQNan) {
10665 Abs, InfWithQnanBitC);
10666 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10673 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10675 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10676 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10679 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10681 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10684 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10685 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10687 appendToRes(NormalRes);
10691 MI.eraseFromParent();
10697 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10698 MI.getFirst4RegLLTs();
10707 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10708 Op1Ty = MRI.getType(Op1Reg);
10709 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10710 Op2Ty = MRI.getType(Op2Reg);
10714 if (MaskTy.isScalar()) {
10722 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10725 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10727 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10729 if (DstTy.isVector()) {
10731 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10732 MaskReg = ShufSplat.getReg(0);
10736 }
else if (!DstTy.isVector()) {
10741 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10745 if (!Op1Ty.getScalarType().isAnyScalar() &&
10746 !Op1Ty.getScalarType().isInteger())
10747 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10749 if (!Op2Ty.getScalarType().isAnyScalar() &&
10750 !Op2Ty.getScalarType().isInteger()) {
10752 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10753 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10756 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10757 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10758 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10763 if (DstTy == Op1TyInt)
10766 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10770 MI.eraseFromParent();
10776 unsigned Opcode =
MI.getOpcode();
10779 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10780 : TargetOpcode::G_UDIV,
10781 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10783 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10784 : TargetOpcode::G_UREM,
10785 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10786 MI.eraseFromParent();
10796 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10800 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10803 MI.eraseFromParent();
10813 Register SrcReg =
MI.getOperand(1).getReg();
10814 LLT Ty = MRI.getType(SrcReg);
10815 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10818 MI.eraseFromParent();
10824 Register SrcReg =
MI.getOperand(1).getReg();
10825 Register DestReg =
MI.getOperand(0).getReg();
10827 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10828 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10831 MI.eraseFromParent();
10837 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10838 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10839 "Expected G_ABDS or G_ABDU instruction");
10841 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10842 LLT Ty = MRI.getType(LHS);
10852 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10854 MI.eraseFromParent();
10860 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10861 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10862 "Expected G_ABDS or G_ABDU instruction");
10864 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10865 LLT Ty = MRI.getType(LHS);
10870 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10871 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10872 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10874 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10875 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10877 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10879 MI.eraseFromParent();
10884 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10889 if (!(SrcTy.getScalarType().isAnyScalar() ||
10890 SrcTy.getScalarType().isInteger())) {
10892 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10893 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10896 if (MRI.getType(DstReg) != TyInt) {
10900 .buildAnd(TyInt, CastedSrc,
10903 DstTy.getScalarSizeInBits())))
10915 MI.eraseFromParent();
10921 Register SrcReg =
MI.getOperand(1).getReg();
10922 LLT SrcTy = MRI.getType(SrcReg);
10923 LLT DstTy = MRI.getType(SrcReg);
10926 if (SrcTy.isScalar()) {
10931 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10942 Register ListPtr =
MI.getOperand(1).getReg();
10943 LLT PtrTy = MRI.getType(ListPtr);
10950 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10952 const Align A(
MI.getOperand(2).getImm());
10954 if (
A > TLI.getMinStackArgumentAlignment()) {
10956 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10957 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10958 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10959 VAList = AndDst.getReg(0);
10966 LLT LLTTy = MRI.getType(Dst);
10969 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10970 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10975 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10977 Align EltAlignment =
DL.getABITypeAlign(Ty);
10980 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10982 MI.eraseFromParent();
10987 unsigned OpCode =
MI.getOpcode();
10988 assert((OpCode == TargetOpcode::G_SMULFIX ||
10989 OpCode == TargetOpcode::G_UMULFIX ||
10990 OpCode == TargetOpcode::G_SMULFIXSAT ||
10991 OpCode == TargetOpcode::G_UMULFIXSAT) &&
10992 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
10993 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10994 LLT Ty = MRI.getType(Dst);
10995 unsigned Scale =
MI.getOperand(3).getImm();
10997 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
10998 OpCode == TargetOpcode::G_UMULFIXSAT);
10999 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
11000 OpCode == TargetOpcode::G_SMULFIXSAT);
11002 if (!Saturating && Scale == 0) {
11004 MI.eraseFromParent();
11010 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
11033 MI.eraseFromParent();
11040 unsigned NumBits = Ty.getScalarSizeInBits();
11042 if (!Ty.isVector() && ValVRegAndVal) {
11043 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
11051 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11074 auto &MF = *
MI.getParent()->getParent();
11079 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11080 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11083 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11084 const auto &DstMMO = **
MI.memoperands_begin();
11086 if (DstAlignCanChange) {
11089 Align NewAlign =
DL.getABITypeAlign(IRTy);
11090 if (NewAlign > Alignment) {
11099 MachineIRBuilder MIB(
MI);
11101 LLT LargestTy = MemOps[0];
11102 for (
unsigned i = 1; i < MemOps.
size(); i++)
11104 LargestTy = MemOps[i];
11116 LLT PtrTy = MRI.getType(Dst);
11117 unsigned DstOff = 0;
11118 unsigned Size = KnownLen;
11119 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11120 LLT Ty = MemOps[
I];
11123 if (TySize >
Size) {
11127 DstOff -= TySize -
Size;
11137 TLI.isTruncateFree(LargestVT, VT))
11138 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11151 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11154 MIB.buildStore(
Value, Ptr, *StoreMMO);
11159 MI.eraseFromParent();
11167 auto &MF = *
MI.getParent()->getParent();
11171 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11172 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11175 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11181 const auto &DstMMO = **
MI.memoperands_begin();
11182 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11184 if (DstAlignCanChange) {
11187 Align NewAlign =
DL.getABITypeAlign(IRTy);
11192 if (!
TRI->hasStackRealignment(MF))
11193 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11194 NewAlign = std::min(NewAlign, *StackAlign);
11196 if (NewAlign > Alignment) {
11205 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11207 MachineIRBuilder MIB(
MI);
11213 LLT SrcTy = MRI.getType(Src);
11214 LLT DstTy = MRI.getType(Dst);
11217 unsigned CurrOffset = 0;
11218 unsigned Size = KnownLen;
11219 for (
auto CopyTy : MemOps) {
11220 TypeSize TySize = CopyTy.getSizeInBytes();
11224 if (TySize >
Size) {
11225 unsigned Overlap = TySize -
Size;
11226 assert(Overlap < CurrOffset &&
11227 "overlapping memcpy load/store spans the whole region or more");
11228 CurrOffset -= Overlap;
11238 if (CurrOffset != 0) {
11240 MIB.buildConstant(
LLT::integer(SrcIndexSize), CurrOffset).getReg(0);
11241 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11243 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11247 if (CurrOffset != 0) {
11248 if (SrcIndexSize != DstIndexSize) {
11250 MIB.buildConstant(
LLT::integer(DstIndexSize), CurrOffset).getReg(0);
11252 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11254 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11255 CurrOffset += TySize;
11259 MI.eraseFromParent();
11267 auto &MF = *
MI.getParent()->getParent();
11271 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11272 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11275 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11276 const auto &DstMMO = **
MI.memoperands_begin();
11277 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11279 if (DstAlignCanChange) {
11282 Align NewAlign =
DL.getABITypeAlign(IRTy);
11287 if (!
TRI->hasStackRealignment(MF))
11288 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11289 NewAlign = std::min(NewAlign, *StackAlign);
11291 if (NewAlign > Alignment) {
11300 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11302 MachineIRBuilder MIB(
MI);
11306 unsigned CurrOffset = 0;
11307 unsigned Size = KnownLen;
11308 SmallVector<Register, 16> LoadVals;
11309 for (
auto CopyTy : MemOps) {
11310 TypeSize TySize = CopyTy.getSizeInBytes();
11314 if (TySize >
Size) {
11315 unsigned Overlap = TySize -
Size;
11316 assert(Overlap < CurrOffset &&
11317 "overlapping memmove load spans the whole region or more");
11318 CurrOffset -= Overlap;
11326 if (CurrOffset != 0) {
11327 LLT SrcTy = MRI.getType(Src);
11330 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11332 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11333 CurrOffset += TySize;
11339 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11340 LLT CopyTy = MemOps[
I];
11345 if (TySize >
Size) {
11346 unsigned Overlap = TySize -
Size;
11347 assert(Overlap < CurrOffset &&
11348 "overlapping memmove store spans the whole region or more");
11349 CurrOffset -= Overlap;
11356 if (CurrOffset != 0) {
11357 LLT DstTy = MRI.getType(Dst);
11360 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11362 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11363 CurrOffset += TySize;
11366 MI.eraseFromParent();
11373 const unsigned Opc =
MI.getOpcode();
11374 assert((
Opc == TargetOpcode::G_MEMCPY ||
11375 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11376 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11377 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11378 "Expected memcpy like instruction");
11380 if (KnownLen == 0) {
11381 MI.eraseFromParent();
11385 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11386 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11389 if (
Opc == TargetOpcode::G_MEMMOVE)
11390 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11392 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11393 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11403 bool DstAlignCanChange;
11404 std::vector<LLT> MemOps;
11406 DstAlignCanChange, MemOps))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static bool hasSwiftErrorArg(MachineFunction &MF)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static RTLIB::Libcall getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI)
static std::pair< int, int > getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy)
Try to break down OrigTy into NarrowTy sized pieces.
static bool hasSameNumEltsOnAllVectorOperands(GenericMachineInstr &MI, MachineRegisterInfo &MRI, std::initializer_list< unsigned > NonVecOpIndices)
Check that all vector operands have same number of elements.
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg, LLT VecTy)
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, Type *FromType)
static void getUnmergeResults(SmallVectorImpl< Register > &Regs, const MachineInstr &MI)
Append the result registers of G_UNMERGE_VALUES MI to Regs.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
#define RTLIBCASE(LibcallPrefix)
static Type * getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Tracks DebugLocs between checkpoints and verifies that they are transferred.
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmTowardZero
static const fltSemantics & IEEEdouble()
static constexpr roundingMode rmNearestTiesToEven
opStatus
IEEE-754R 7: Default exception handling.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
APInt bitcastToAPInt() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
void negate()
Negate this APInt in place.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, unsigned hiBit)
Wrap version of getBitsSet.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
LLT getLLTTy(const MachineRegisterInfo &MRI) const
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Register getValueReg() const
Get the stored value register.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Represents a insert subvector.
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
Represents a threeway compare.
A base class for all GenericMachineInstrs.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
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
LLT changeToInteger() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr ElementCount getElementCount() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
constexpr LLT changeVectorElementType(LLT NewEltTy) const
Returns a vector with the same number of elements but the new element type.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLT changeVectorElementCount(ElementCount EC) const
Return a vector with the same element type and the new element count.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
static LLT floatIEEE(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerThreewayCompare(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI)
LLVM_ABI LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI)
Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
LLVM_ABI LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty)
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSSUBE(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerSMULH_UMULH(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerLoad(GAnyLoad &MI)
LLVM_ABI LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerAbsToAddXor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPEXT_BF16(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizerHelper::LegalizeResult createAtomicLibcall(MachineInstr &MI) const
LLVM_ABI LegalizeResult lowerFConstant(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerBitreverse(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
Legalize a vector instruction by increasing the number of vector elements involved and ignoring the a...
LLVM_ABI LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTLS(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy)
Multi-way shift legalization: directly split wide shifts into target-sized parts in a single step,...
LLVM_ABI Register lowerRoundInexactToOdd(LLT ResultTy, Register Op)
LLVM_ABI LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, Register Dst, Register Src, uint64_t KnownLen, Align Alignment, bool DstAlignCanChange, ArrayRef< LLT > MemOps)
LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI Register buildConstantShiftPart(unsigned Opcode, unsigned PartIdx, unsigned NumParts, ArrayRef< Register > SrcParts, const ShiftParams &Params, LLT TargetTy, LLT ShiftAmtTy)
Generates a single output part for constant shifts using direct indexing.
LLVM_ABI void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by truncating the operand's ty...
LLVM_ABI LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI, unsigned NumElts)
LLVM_ABI LegalizeResult lowerFPTOUI(MachineInstr &MI)
const TargetLowering & getTargetLowering() const
LLVM_ABI LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
LLVM_ABI LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult bitcastInsertSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_INSERT_SUBVECTOR to CastTy.
LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B, const LibcallLoweringInfo *Libcalls=nullptr)
LLVM_ABI LegalizeResult lowerUnmergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by replacing the value type.
LLVM_ABI LegalizeResult scalarizeVectorBooleanStore(GStore &MI)
Given a store of a boolean vector, scalarize it.
LLVM_ABI LegalizeResult lowerBitcast(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerReadWriteRegister(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, LLT HalfTy, LLT ShiftAmtTy)
LLVM_ABI LegalizeResult lowerISFPCLASS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPExtAndTruncMem(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFAbs(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerVectorReduction(MachineInstr &MI)
const LegalizerInfo & getLegalizerInfo() const
Expose LegalizerInfo so the clients can re-use.
LLVM_ABI LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult fewerElementsVectorMultiEltType(GenericMachineInstr &MI, unsigned NumElts, std::initializer_list< unsigned > NonVecOpIndices={})
Handles most opcodes.
LLVM_ABI LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarShiftByConstantMultiway(MachineInstr &MI, const APInt &Amt, LLT TargetTy, LLT ShiftAmtTy)
Optimized path for constant shift amounts using static indexing.
LLVM_ABI void widenScalarSrcUsingFPExt(MachineInstr &MI, LLT WideTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val)
Create a store of Val to a stack temporary and return a load as the same type as Res.
LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMODF(MachineInstr &MI)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ AlreadyLegal
Instruction was already legal and no change was made to the MachineFunction.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerFCopySign(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSADDE(MachineInstr &MI)
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
LLVM_ABI LegalizeResult lowerFunnelShift(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F32_TO_BF16(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI LegalizeResult conversionLibcall(MachineInstr &MI, Type *ToType, Type *FromType, LostDebugLocObserver &LocObserver, bool IsSigned=false) const
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFPTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
LLVM_ABI LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
LLVM_ABI LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerFFloor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_BF16(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult fewerElementsVectorSeqReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize, Align Alignment, LLT PtrTy)
LLVM_ABI LegalizeResult lowerFPTOSI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerUITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerShuffleVector(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerMergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult createMemLibcall(MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver) const
Create a libcall to memcpy et al.
LLVM_ABI LegalizeResult lowerVECTOR_COMPRESS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMulfix(MachineInstr &MI)
LLVM_ABI void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by producing a vector with und...
LLVM_ABI LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF32WithSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult createLibcall(const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr) const
Helper function that creates a libcall to the given Name using the given calling convention CC.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerTruncSat(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI void widenScalarDstUsingFPTrunc(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI LegalizeResult lowerTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBswap(MachineInstr &MI)
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
LLVM_ABI LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const
Return the alignment to use for a stack temporary object with the given type.
LLVM_ABI LegalizeResult lowerConstant(MachineInstr &MI)
LLVM_ABI Register coerceToInteger(Register Val)
Cast the given value to an LLT::integer with an equivalent size.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LLVM_ABI LegalizeResult simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver) const
LLVM_ABI LegalizeResult legalizeInstrStep(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Replace MI by a sequence of legal instructions that can implement the same operation.
LLVM_ABI LegalizeResult lowerFMinimumMaximum(MachineInstr &MI)
Tracks which library functions to use for a particular subtarget or function.
TypeSize getValue() const
void checkpoint(bool CheckDebugLocs=true)
Call this to indicate that it's a good point to assess whether locations have been lost.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
LLVM_ABI StringRef getString() const
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
LLVM_ABI iterator getFirstTerminatorForward()
Finds the first terminator in a block by scanning forward.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Helper class to build MachineInstr.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_UREM Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0)
Build and insert integer negation Zero = G_CONSTANT 0 Res = G_SUB Zero, Op0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_UITOFP Src0.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
Represent a constant reference to a string, i.e.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual bool supportSwiftError() const
Return true if the target supports swifterror attribute.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
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 bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
ImplicitDefMatch m_GImplicitDef()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(Register Def, const MachineRegisterInfo &MRI)
Determines if Def defines a constant integer or a splat vector of constant integers.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, llvm::function_ref< 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 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.)
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
LLVM_ABI bool canLowerMemCpyFamily(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned MaxLen, Register &Dst, Register &Src, uint64_t &KnownLen, Align &Alignment, bool &DstAlignCanChange, std::vector< LLT > &MemOps)
Matcher for memcpy-like instructions.
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
bool isKnownNeverZero() const
Return true if it's known this can never be a zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.