44#define DEBUG_TYPE "legalizer"
57static std::pair<int, int>
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);
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:
523 return TLI.supportSwiftError() &&
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)
672 Args.push_back({MO.getReg(), OpType, 0});
686 LLT DstTy =
MRI.getType(DstSin);
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;
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;
1609 unsigned Offset =
I * NarrowSize;
1616 unsigned LeftoverBits = TotalSize -
NumParts * NarrowSize;
1618 if (LeftoverBits != 0) {
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:
1686 case TargetOpcode::G_SMULH:
1688 case TargetOpcode::G_EXTRACT:
1690 case TargetOpcode::G_INSERT:
1692 case TargetOpcode::G_LOAD: {
1694 Register DstReg = LoadMI.getDstReg();
1695 LLT DstTy = MRI.getType(DstReg);
1699 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1700 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1701 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1703 LoadMI.eraseFromParent();
1709 case TargetOpcode::G_ZEXTLOAD:
1710 case TargetOpcode::G_SEXTLOAD:
1711 case TargetOpcode::G_FPEXTLOAD: {
1713 Register DstReg = LoadMI.getDstReg();
1714 Register PtrReg = LoadMI.getPointerReg();
1716 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1717 auto &MMO = LoadMI.getMMO();
1720 if (MemSize == NarrowSize) {
1722 }
else if (MemSize < NarrowSize) {
1723 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1724 }
else if (MemSize > NarrowSize) {
1736 LoadMI.eraseFromParent();
1739 case TargetOpcode::G_STORE: {
1742 Register SrcReg = StoreMI.getValueReg();
1743 LLT SrcTy = MRI.getType(SrcReg);
1744 if (SrcTy.isVector())
1747 int NumParts = SizeOp0 / NarrowSize;
1749 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1750 if (SrcTy.isVector() && LeftoverBits != 0)
1753 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1754 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1756 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1757 StoreMI.eraseFromParent();
1763 case TargetOpcode::G_FPTRUNCSTORE: {
1765 Register SrcReg = StoreMI.getValueReg();
1766 Register PtrReg = StoreMI.getPointerReg();
1768 auto &MMO = StoreMI.getMMO();
1770 if (MemSize > NarrowSize) {
1774 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1775 if (MemSize == NarrowSize) {
1777 }
else if (MemSize < NarrowSize) {
1778 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1782 StoreMI.eraseFromParent();
1785 case TargetOpcode::G_SELECT:
1787 case TargetOpcode::G_AND:
1788 case TargetOpcode::G_OR:
1789 case TargetOpcode::G_XOR: {
1801 case TargetOpcode::G_SHL:
1802 case TargetOpcode::G_LSHR:
1803 case TargetOpcode::G_ASHR:
1805 case TargetOpcode::G_CTLZ:
1806 case TargetOpcode::G_CTLZ_ZERO_POISON:
1807 case TargetOpcode::G_CTTZ:
1808 case TargetOpcode::G_CTTZ_ZERO_POISON:
1809 case TargetOpcode::G_CTLS:
1810 case TargetOpcode::G_CTPOP:
1812 switch (
MI.getOpcode()) {
1813 case TargetOpcode::G_CTLZ:
1814 case TargetOpcode::G_CTLZ_ZERO_POISON:
1816 case TargetOpcode::G_CTTZ:
1817 case TargetOpcode::G_CTTZ_ZERO_POISON:
1819 case TargetOpcode::G_CTPOP:
1821 case TargetOpcode::G_CTLS:
1831 case TargetOpcode::G_INTTOPTR:
1839 case TargetOpcode::G_PTRTOINT:
1847 case TargetOpcode::G_PHI: {
1850 if (SizeOp0 % NarrowSize != 0)
1853 unsigned NumParts = SizeOp0 / NarrowSize;
1857 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1865 for (
unsigned i = 0; i <
NumParts; ++i) {
1866 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1868 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1869 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1870 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1873 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1875 MI.eraseFromParent();
1878 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1879 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1883 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1889 case TargetOpcode::G_ICMP: {
1891 LLT SrcTy = MRI.getType(LHS);
1897 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1903 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1904 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1910 LLT ResTy = MRI.getType(Dst);
1915 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1917 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1918 auto LHS = std::get<0>(LHSAndRHS);
1919 auto RHS = std::get<1>(LHSAndRHS);
1920 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1927 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1928 auto LHS = std::get<0>(LHSAndRHS);
1929 auto RHS = std::get<1>(LHSAndRHS);
1930 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1931 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1932 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1933 TargetOpcode::G_ZEXT);
1940 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1941 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1942 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1947 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1951 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1956 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1960 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1963 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1966 LHSPartRegs[
I], RHSPartRegs[
I]);
1967 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1973 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1982 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1986 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1987 RHSLeftoverRegs[
I]);
1989 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1990 RHSLeftoverRegs[
I]);
1993 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1994 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
2000 MI.eraseFromParent();
2003 case TargetOpcode::G_FCMP:
2012 case TargetOpcode::G_SEXT_INREG: {
2016 int64_t SizeInBits =
MI.getOperand(2).getImm();
2025 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2026 MO1.
setReg(TruncMIB.getReg(0));
2029 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2041 if (SizeOp0 % NarrowSize != 0)
2043 int NumParts = SizeOp0 / NarrowSize;
2051 for (
int i = 0; i <
NumParts; ++i) {
2052 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2067 for (
int i = 0; i <
NumParts; ++i) {
2070 PartialExtensionReg = DstRegs.
back();
2072 assert(PartialExtensionReg &&
2073 "Expected to visit partial extension before full");
2074 if (FullExtensionReg) {
2079 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2081 FullExtensionReg = DstRegs.
back();
2086 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2089 PartialExtensionReg = DstRegs.
back();
2095 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2096 MI.eraseFromParent();
2099 case TargetOpcode::G_BSWAP:
2100 case TargetOpcode::G_BITREVERSE: {
2101 if (SizeOp0 % NarrowSize != 0)
2106 unsigned NumParts = SizeOp0 / NarrowSize;
2110 for (
unsigned i = 0; i <
NumParts; ++i) {
2111 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2112 {SrcRegs[NumParts - 1 - i]});
2116 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2119 MI.eraseFromParent();
2122 case TargetOpcode::G_PTR_ADD:
2123 case TargetOpcode::G_PTRMASK: {
2131 case TargetOpcode::G_FPTOUI:
2132 case TargetOpcode::G_FPTOSI:
2133 case TargetOpcode::G_FPTOUI_SAT:
2134 case TargetOpcode::G_FPTOSI_SAT:
2136 case TargetOpcode::G_FPEXT:
2143 case TargetOpcode::G_FLDEXP:
2144 case TargetOpcode::G_STRICT_FLDEXP:
2146 case TargetOpcode::G_VSCALE: {
2148 LLT Ty = MRI.getType(Dst);
2152 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2153 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2154 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2157 MI.eraseFromParent();
2164 LLT Ty = MRI.getType(Val);
2165 if (Ty.isScalar() && !Ty.isFloat())
2172 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2174 if (Ty.isPointer()) {
2175 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2177 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2183 if (Ty.isPointerVector())
2184 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2185 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2189 unsigned OpIdx,
unsigned ExtOpcode) {
2191 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2192 MO.
setReg(ExtB.getReg(0));
2198 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2200 MO.
setReg(ExtB.getReg(0));
2206 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2207 MO.
setReg(ExtB.getReg(0));
2211 unsigned OpIdx,
unsigned TruncOpcode) {
2213 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2215 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2222 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2224 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2229 unsigned OpIdx,
unsigned ExtOpcode) {
2231 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2233 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2242 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2244 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2250 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2260 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2267LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2272 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2273 if (DstTy.isVector())
2276 LLT SrcTy =
MRI.getType(Src1Reg);
2277 const int DstSize = DstTy.getSizeInBits();
2278 const int SrcSize = SrcTy.getSizeInBits();
2280 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2282 unsigned NumOps =
MI.getNumOperands();
2283 unsigned NumSrc =
MI.getNumOperands() - 1;
2284 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2286 if (WideSize >= DstSize) {
2290 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2291 const unsigned Offset = (
I - 1) * PartSize;
2299 MRI.createGenericVirtualRegister(WideTy);
2304 ResultReg = NextResult;
2307 if (WideSize > DstSize)
2309 else if (DstTy.isPointer())
2311 else if (DstTy != WideTy)
2314 MI.eraseFromParent();
2339 const int GCD = std::gcd(SrcSize, WideSize);
2349 if (GCD == SrcSize) {
2352 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2353 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2359 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2361 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2365 const int PartsPerGCD = WideSize / GCD;
2369 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2371 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2378 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2380 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2381 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2384 MI.eraseFromParent();
2389LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2394 int NumDst =
MI.getNumOperands() - 1;
2395 Register SrcReg =
MI.getOperand(NumDst).getReg();
2396 LLT SrcTy = MRI.getType(SrcReg);
2400 Register Dst0Reg =
MI.getOperand(0).getReg();
2401 LLT DstTy = MRI.getType(Dst0Reg);
2410 dbgs() <<
"Not casting non-integral address space integer\n");
2415 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2423 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2432 SrcTy = MRI.getType(SrcReg);
2436 for (
int I = 1;
I != NumDst; ++
I) {
2437 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2438 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2442 MI.eraseFromParent();
2453 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2457 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2460 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2478 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2483 if (PartsPerRemerge == 1) {
2486 for (
int I = 0;
I != NumUnmerge; ++
I) {
2487 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2489 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2490 int Idx =
I * PartsPerUnmerge + J;
2492 MIB.addDef(
MI.getOperand(Idx).getReg());
2495 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2499 MIB.addUse(Unmerge.getReg(
I));
2502 SmallVector<Register, 16> Parts;
2503 for (
int J = 0; J != NumUnmerge; ++J)
2504 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2507 for (
int I = 0;
I != NumDst; ++
I) {
2508 for (
int J = 0; J < PartsPerRemerge; ++J) {
2509 const int Idx =
I * PartsPerRemerge + J;
2513 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2514 RemergeParts.
clear();
2518 MI.eraseFromParent();
2523LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2525 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2526 unsigned Offset =
MI.getOperand(2).getImm();
2529 if (SrcTy.
isVector() || DstTy.isVector())
2541 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2545 if (DstTy.isPointer())
2552 MI.eraseFromParent();
2557 LLT ShiftTy = SrcTy;
2566 MI.eraseFromParent();
2597LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2599 if (TypeIdx != 0 || WideTy.
isVector())
2609LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2613 std::optional<Register> CarryIn;
2614 switch (
MI.getOpcode()) {
2617 case TargetOpcode::G_SADDO:
2618 Opcode = TargetOpcode::G_ADD;
2619 ExtOpcode = TargetOpcode::G_SEXT;
2621 case TargetOpcode::G_SSUBO:
2622 Opcode = TargetOpcode::G_SUB;
2623 ExtOpcode = TargetOpcode::G_SEXT;
2625 case TargetOpcode::G_UADDO:
2626 Opcode = TargetOpcode::G_ADD;
2627 ExtOpcode = TargetOpcode::G_ZEXT;
2629 case TargetOpcode::G_USUBO:
2630 Opcode = TargetOpcode::G_SUB;
2631 ExtOpcode = TargetOpcode::G_ZEXT;
2633 case TargetOpcode::G_SADDE:
2634 Opcode = TargetOpcode::G_UADDE;
2635 ExtOpcode = TargetOpcode::G_SEXT;
2636 CarryIn =
MI.getOperand(4).getReg();
2638 case TargetOpcode::G_SSUBE:
2639 Opcode = TargetOpcode::G_USUBE;
2640 ExtOpcode = TargetOpcode::G_SEXT;
2641 CarryIn =
MI.getOperand(4).getReg();
2643 case TargetOpcode::G_UADDE:
2644 Opcode = TargetOpcode::G_UADDE;
2645 ExtOpcode = TargetOpcode::G_ZEXT;
2646 CarryIn =
MI.getOperand(4).getReg();
2648 case TargetOpcode::G_USUBE:
2649 Opcode = TargetOpcode::G_USUBE;
2650 ExtOpcode = TargetOpcode::G_ZEXT;
2651 CarryIn =
MI.getOperand(4).getReg();
2667 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2668 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2672 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2674 .buildInstr(Opcode, {WideTy, CarryOutTy},
2675 {LHSExt, RHSExt, *CarryIn})
2678 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2680 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2681 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2682 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2687 MI.eraseFromParent();
2692LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2694 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2695 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2696 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2697 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2698 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2711 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2718 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2722 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2723 {ShiftL, ShiftR},
MI.getFlags());
2728 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2731 MI.eraseFromParent();
2736LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2745 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2747 LLT SrcTy = MRI.getType(
LHS);
2748 LLT OverflowTy = MRI.getType(OriginalOverflow);
2755 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2756 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2757 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2764 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2766 MachineInstrBuilder Mulo;
2767 if (WideMulCanOverflow)
2768 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2769 {LeftOperand, RightOperand});
2771 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2776 MachineInstrBuilder ExtResult;
2783 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2787 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2790 if (WideMulCanOverflow) {
2798 MI.eraseFromParent();
2804 unsigned Opcode =
MI.getOpcode();
2808 case TargetOpcode::G_ATOMICRMW_XCHG:
2809 case TargetOpcode::G_ATOMICRMW_ADD:
2810 case TargetOpcode::G_ATOMICRMW_SUB:
2811 case TargetOpcode::G_ATOMICRMW_AND:
2812 case TargetOpcode::G_ATOMICRMW_OR:
2813 case TargetOpcode::G_ATOMICRMW_XOR:
2814 case TargetOpcode::G_ATOMICRMW_MIN:
2815 case TargetOpcode::G_ATOMICRMW_MAX:
2816 case TargetOpcode::G_ATOMICRMW_UMIN:
2817 case TargetOpcode::G_ATOMICRMW_UMAX:
2818 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2824 case TargetOpcode::G_ATOMIC_CMPXCHG:
2825 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2832 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2842 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2847 case TargetOpcode::G_EXTRACT:
2848 return widenScalarExtract(
MI, TypeIdx, WideTy);
2849 case TargetOpcode::G_INSERT:
2850 return widenScalarInsert(
MI, TypeIdx, WideTy);
2851 case TargetOpcode::G_MERGE_VALUES:
2852 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2853 case TargetOpcode::G_UNMERGE_VALUES:
2854 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2855 case TargetOpcode::G_SADDO:
2856 case TargetOpcode::G_SSUBO:
2857 case TargetOpcode::G_UADDO:
2858 case TargetOpcode::G_USUBO:
2859 case TargetOpcode::G_SADDE:
2860 case TargetOpcode::G_SSUBE:
2861 case TargetOpcode::G_UADDE:
2862 case TargetOpcode::G_USUBE:
2863 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2864 case TargetOpcode::G_UMULO:
2865 case TargetOpcode::G_SMULO:
2866 return widenScalarMulo(
MI, TypeIdx, WideTy);
2867 case TargetOpcode::G_SADDSAT:
2868 case TargetOpcode::G_SSUBSAT:
2869 case TargetOpcode::G_SSHLSAT:
2870 case TargetOpcode::G_UADDSAT:
2871 case TargetOpcode::G_USUBSAT:
2872 case TargetOpcode::G_USHLSAT:
2873 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2874 case TargetOpcode::G_CTTZ:
2875 case TargetOpcode::G_CTTZ_ZERO_POISON:
2876 case TargetOpcode::G_CTLZ:
2877 case TargetOpcode::G_CTLZ_ZERO_POISON:
2878 case TargetOpcode::G_CTLS:
2879 case TargetOpcode::G_CTPOP: {
2892 case TargetOpcode::G_CTTZ:
2893 case TargetOpcode::G_CTTZ_ZERO_POISON:
2894 case TargetOpcode::G_CTLZ_ZERO_POISON:
2895 ExtOpc = TargetOpcode::G_ANYEXT;
2897 case TargetOpcode::G_CTLS:
2898 ExtOpc = TargetOpcode::G_SEXT;
2901 ExtOpc = TargetOpcode::G_ZEXT;
2904 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2905 LLT CurTy = MRI.getType(SrcReg);
2906 unsigned NewOpc = Opcode;
2907 if (NewOpc == TargetOpcode::G_CTTZ) {
2914 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2916 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2922 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2932 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2934 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2939 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2940 Opcode == TargetOpcode::G_CTLZ
2945 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2946 MI.eraseFromParent();
2949 case TargetOpcode::G_BSWAP: {
2953 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2954 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2955 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2958 MI.getOperand(0).setReg(DstExt);
2962 LLT Ty = MRI.getType(DstReg);
2964 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2965 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2971 case TargetOpcode::G_BITREVERSE: {
2975 LLT Ty = MRI.getType(DstReg);
2978 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2980 MI.getOperand(0).setReg(DstExt);
2983 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2984 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2989 case TargetOpcode::G_FREEZE:
2990 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2997 case TargetOpcode::G_ABS:
3004 case TargetOpcode::G_ADD:
3005 case TargetOpcode::G_AND:
3006 case TargetOpcode::G_MUL:
3007 case TargetOpcode::G_OR:
3008 case TargetOpcode::G_XOR:
3009 case TargetOpcode::G_SUB:
3010 case TargetOpcode::G_SHUFFLE_VECTOR:
3026 case TargetOpcode::G_SBFX:
3027 case TargetOpcode::G_UBFX:
3041 case TargetOpcode::G_SHL:
3061 case TargetOpcode::G_ROTR:
3062 case TargetOpcode::G_ROTL:
3071 case TargetOpcode::G_SDIV:
3072 case TargetOpcode::G_SREM:
3073 case TargetOpcode::G_SMIN:
3074 case TargetOpcode::G_SMAX:
3075 case TargetOpcode::G_ABDS:
3083 case TargetOpcode::G_SDIVREM:
3093 case TargetOpcode::G_ASHR:
3094 case TargetOpcode::G_LSHR:
3098 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3099 : TargetOpcode::G_ZEXT;
3112 case TargetOpcode::G_UDIV:
3113 case TargetOpcode::G_UREM:
3114 case TargetOpcode::G_ABDU:
3121 case TargetOpcode::G_UDIVREM:
3130 case TargetOpcode::G_UMIN:
3131 case TargetOpcode::G_UMAX: {
3132 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3134 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3138 ? TargetOpcode::G_SEXT
3139 : TargetOpcode::G_ZEXT;
3149 case TargetOpcode::G_SELECT:
3159 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3166 case TargetOpcode::G_FPEXT:
3174 case TargetOpcode::G_FPTOSI:
3175 case TargetOpcode::G_FPTOUI:
3176 case TargetOpcode::G_INTRINSIC_LRINT:
3177 case TargetOpcode::G_INTRINSIC_LLRINT:
3178 case TargetOpcode::G_IS_FPCLASS:
3188 case TargetOpcode::G_SITOFP:
3198 case TargetOpcode::G_UITOFP:
3208 case TargetOpcode::G_FPTOSI_SAT:
3209 case TargetOpcode::G_FPTOUI_SAT:
3214 LLT Ty = MRI.getType(OldDst);
3215 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3217 MI.getOperand(0).setReg(ExtReg);
3218 uint64_t ShortBits = Ty.getScalarSizeInBits();
3221 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3232 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3233 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3241 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3249 case TargetOpcode::G_LOAD:
3250 case TargetOpcode::G_SEXTLOAD:
3251 case TargetOpcode::G_ZEXTLOAD:
3252 case TargetOpcode::G_FPEXTLOAD:
3258 case TargetOpcode::G_STORE: {
3262 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3263 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3264 if (!Ty.isScalar()) {
3272 MI.setMemRefs(MF, {NewMMO});
3279 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3280 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3286 case TargetOpcode::G_FPTRUNCSTORE:
3293 case TargetOpcode::G_CONSTANT: {
3296 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3297 MRI.getType(
MI.getOperand(0).getReg()));
3298 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3299 ExtOpc == TargetOpcode::G_ANYEXT) &&
3302 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3306 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3312 case TargetOpcode::G_FCONSTANT: {
3318 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3320 MI.eraseFromParent();
3323 case TargetOpcode::G_IMPLICIT_DEF: {
3329 case TargetOpcode::G_BRCOND:
3335 case TargetOpcode::G_FCMP:
3346 case TargetOpcode::G_ICMP:
3351 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3355 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3356 unsigned ExtOpcode =
3360 ? TargetOpcode::G_SEXT
3361 : TargetOpcode::G_ZEXT;
3368 case TargetOpcode::G_PTR_ADD:
3369 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3375 case TargetOpcode::G_PHI: {
3376 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3379 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3391 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3394 LLT VecTy = MRI.getType(VecReg);
3398 TargetOpcode::G_ANYEXT);
3412 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3428 LLT VecTy = MRI.getType(VecReg);
3447 case TargetOpcode::G_FADD:
3448 case TargetOpcode::G_FMUL:
3449 case TargetOpcode::G_FSUB:
3450 case TargetOpcode::G_FMA:
3451 case TargetOpcode::G_FMAD:
3452 case TargetOpcode::G_FNEG:
3453 case TargetOpcode::G_FABS:
3454 case TargetOpcode::G_FCANONICALIZE:
3455 case TargetOpcode::G_FMINNUM:
3456 case TargetOpcode::G_FMAXNUM:
3457 case TargetOpcode::G_FMINNUM_IEEE:
3458 case TargetOpcode::G_FMAXNUM_IEEE:
3459 case TargetOpcode::G_FMINIMUM:
3460 case TargetOpcode::G_FMAXIMUM:
3461 case TargetOpcode::G_FMINIMUMNUM:
3462 case TargetOpcode::G_FMAXIMUMNUM:
3463 case TargetOpcode::G_FDIV:
3464 case TargetOpcode::G_FREM:
3465 case TargetOpcode::G_FCEIL:
3466 case TargetOpcode::G_FFLOOR:
3467 case TargetOpcode::G_FCOS:
3468 case TargetOpcode::G_FSIN:
3469 case TargetOpcode::G_FTAN:
3470 case TargetOpcode::G_FACOS:
3471 case TargetOpcode::G_FASIN:
3472 case TargetOpcode::G_FATAN:
3473 case TargetOpcode::G_FATAN2:
3474 case TargetOpcode::G_FCOSH:
3475 case TargetOpcode::G_FSINH:
3476 case TargetOpcode::G_FTANH:
3477 case TargetOpcode::G_FLOG10:
3478 case TargetOpcode::G_FLOG:
3479 case TargetOpcode::G_FLOG2:
3480 case TargetOpcode::G_FRINT:
3481 case TargetOpcode::G_FNEARBYINT:
3482 case TargetOpcode::G_FSQRT:
3483 case TargetOpcode::G_FEXP:
3484 case TargetOpcode::G_FEXP2:
3485 case TargetOpcode::G_FEXP10:
3486 case TargetOpcode::G_FPOW:
3487 case TargetOpcode::G_INTRINSIC_TRUNC:
3488 case TargetOpcode::G_INTRINSIC_ROUND:
3489 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3493 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3499 case TargetOpcode::G_FMODF: {
3509 case TargetOpcode::G_FPOWI:
3510 case TargetOpcode::G_FLDEXP:
3511 case TargetOpcode::G_STRICT_FLDEXP: {
3513 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3534 case TargetOpcode::G_FFREXP: {
3547 case TargetOpcode::G_LROUND:
3548 case TargetOpcode::G_LLROUND:
3559 case TargetOpcode::G_INTTOPTR:
3567 case TargetOpcode::G_PTRTOINT:
3575 case TargetOpcode::G_BUILD_VECTOR: {
3579 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3585 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3593 case TargetOpcode::G_SEXT_INREG:
3602 case TargetOpcode::G_PTRMASK: {
3610 case TargetOpcode::G_VECREDUCE_ADD: {
3619 case TargetOpcode::G_VECREDUCE_FADD:
3620 case TargetOpcode::G_VECREDUCE_FMUL:
3621 case TargetOpcode::G_VECREDUCE_FMIN:
3622 case TargetOpcode::G_VECREDUCE_FMAX:
3623 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3624 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3629 LLT VecTy = MRI.getType(VecReg);
3636 case TargetOpcode::G_VSCALE: {
3643 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3648 case TargetOpcode::G_SPLAT_VECTOR: {
3657 case TargetOpcode::G_INSERT_SUBVECTOR: {
3669 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3670 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3671 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3675 auto SplatZero =
MIRBuilder.buildSplatVector(
3680 MI.eraseFromParent();
3684 case TargetOpcode::G_BITCAST:
3696 if (MRI.getType(Dst) == MRI.getType(Src)) {
3697 Observer.changingAllUsesOfReg(MRI, Dst);
3698 MRI.replaceRegWith(Dst, Src);
3699 Observer.finishedChangingAllUsesOfReg();
3700 MI.eraseFromParent();
3709 auto Unmerge =
B.buildUnmerge(Ty, Src);
3710 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3719 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3721 LLT DstLLT =
MRI.getType(DstReg);
3733 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3742 MI.eraseFromParent();
3750 const ConstantFP *ConstantVal =
MI.getOperand(1).getFPImm();
3753 bool ForCodeSize =
MIRBuilder.getMF().getFunction().hasOptSize();
3754 if (TLI.getFPImmAction(
Imm, MRI.getType(Dst), ForCodeSize) ==
3760 MI.eraseFromParent();
3766 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3767 if (SrcTy.isVector()) {
3771 if (DstTy.isVector()) {
3786 unsigned PieceSize =
3802 MI.eraseFromParent();
3807 LLT::vector(SrcEC * (SrcEltSize / PieceSize), PieceTy);
3809 MIRBuilder.buildBitcast(PiecesVecTy, Src).getReg(0);
3811 MI.eraseFromParent();
3818 LLT DstCastTy = DstEltTy;
3819 LLT SrcPartTy = SrcEltTy;
3823 if (NumSrcElt < NumDstElt) {
3834 SrcPartTy = SrcEltTy;
3835 }
else if (NumSrcElt > NumDstElt) {
3847 DstCastTy = DstEltTy;
3852 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3856 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3857 MI.eraseFromParent();
3861 if (DstTy.isVector()) {
3864 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3865 MI.eraseFromParent();
3881 unsigned NewEltSize,
3882 unsigned OldEltSize) {
3883 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3884 LLT IdxTy =
B.getMRI()->getType(Idx);
3887 auto OffsetMask =
B.buildConstant(
3889 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3890 return B.buildShl(IdxTy, OffsetIdx,
3891 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3906 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3910 unsigned OldNumElts = SrcVecTy.getNumElements();
3917 if (NewNumElts > OldNumElts) {
3928 if (NewNumElts % OldNumElts != 0)
3932 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3936 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3939 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3941 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3942 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3943 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3944 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3945 NewOps[
I] = Elt.getReg(0);
3948 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3950 MI.eraseFromParent();
3954 if (NewNumElts < OldNumElts) {
3955 if (NewEltSize % OldEltSize != 0)
3977 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3978 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3981 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3985 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3986 ScaledIdx).getReg(0);
3994 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3996 MI.eraseFromParent();
4010 LLT TargetTy =
B.getMRI()->getType(TargetReg);
4011 LLT InsertTy =
B.getMRI()->getType(InsertReg);
4012 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
4013 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
4016 auto EltMask =
B.buildConstant(
4020 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
4021 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
4024 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
4028 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
4042 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
4043 MI.getFirst4RegLLTs();
4055 if (NewNumElts < OldNumElts) {
4056 if (NewEltSize % OldEltSize != 0)
4065 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4066 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4069 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4073 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4074 ScaledIdx).getReg(0);
4084 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4085 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4089 MI.eraseFromParent();
4119 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4123 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4124 return UnableToLegalize;
4129 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4131 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4140 MI.eraseFromParent();
4158 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4159 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4169 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4170 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4172 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4173 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4175 MI.eraseFromParent();
4201 uint64_t Idx = ES->getIndexImm();
4205 LLT DstTy = MRI.getType(Dst);
4206 LLT SrcTy = MRI.getType(Src);
4212 if (DstTy == CastTy)
4220 if (CastEltSize < DstEltSize)
4223 auto AdjustAmt = CastEltSize / DstEltSize;
4224 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4225 SrcTyMinElts % AdjustAmt != 0)
4230 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4231 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4234 ES->eraseFromParent();
4265 uint64_t Idx = ES->getIndexImm();
4269 LLT DstTy = MRI.getType(Dst);
4270 LLT BigVecTy = MRI.getType(BigVec);
4273 if (DstTy == CastTy)
4288 if (CastEltSize < DstEltSize)
4291 auto AdjustAmt = CastEltSize / DstEltSize;
4292 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4293 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4299 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4302 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4305 ES->eraseFromParent();
4313 LLT DstTy = MRI.getType(DstReg);
4323 if (MemSizeInBits != MemStoreSizeInBits) {
4340 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4344 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4345 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4347 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4350 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4352 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4355 if (DstTy != LoadTy)
4363 if (
MIRBuilder.getDataLayout().isBigEndian())
4381 uint64_t LargeSplitSize, SmallSplitSize;
4386 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4393 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4396 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4407 if (Alignment.value() * 8 > MemSizeInBits &&
4412 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4429 LLT PtrTy = MRI.getType(PtrReg);
4435 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4438 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4439 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4440 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4442 SmallPtr, *SmallMMO);
4444 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4445 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4447 if (AnyExtTy == DstTy)
4448 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4450 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4452 if (IntDstTy == DstTy) {
4459 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4465 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4482 LLT SrcTy = MRI.getType(SrcReg);
4490 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4496 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4498 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4502 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4506 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4521 uint64_t LargeSplitSize, SmallSplitSize;
4528 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4531 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4540 if (SrcTy.isPointer()) {
4545 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4548 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4549 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4552 LLT PtrTy = MRI.getType(PtrReg);
4554 LargeSplitSize / 8);
4555 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4561 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4562 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4571 LLT SrcTy = MRI.getType(SrcReg);
4577 assert(SrcTy.isVector() &&
"Expect a vector store type");
4584 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4588 auto Elt =
MIRBuilder.buildExtractVectorElement(
4589 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4590 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4591 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4597 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4598 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4602 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4613 switch (
MI.getOpcode()) {
4614 case TargetOpcode::G_LOAD: {
4632 case TargetOpcode::G_STORE: {
4648 case TargetOpcode::G_SELECT: {
4652 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4654 dbgs() <<
"bitcast action not implemented for vector select\n");
4665 case TargetOpcode::G_AND:
4666 case TargetOpcode::G_OR:
4667 case TargetOpcode::G_XOR: {
4675 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4677 case TargetOpcode::G_INSERT_VECTOR_ELT:
4679 case TargetOpcode::G_CONCAT_VECTORS:
4681 case TargetOpcode::G_SHUFFLE_VECTOR:
4683 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4685 case TargetOpcode::G_INSERT_SUBVECTOR:
4693void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4702 switch(
MI.getOpcode()) {
4705 case TargetOpcode::G_FCONSTANT:
4707 case TargetOpcode::G_BITCAST:
4709 case TargetOpcode::G_SREM:
4710 case TargetOpcode::G_UREM: {
4711 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4713 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4714 {MI.getOperand(1), MI.getOperand(2)});
4716 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4718 MI.eraseFromParent();
4721 case TargetOpcode::G_SADDO:
4722 case TargetOpcode::G_SSUBO:
4724 case TargetOpcode::G_SADDE:
4726 case TargetOpcode::G_SSUBE:
4728 case TargetOpcode::G_UMULH:
4729 case TargetOpcode::G_SMULH:
4731 case TargetOpcode::G_SMULO:
4732 case TargetOpcode::G_UMULO: {
4735 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4736 LLT Ty = MRI.getType(Res);
4738 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4739 ? TargetOpcode::G_SMULH
4740 : TargetOpcode::G_UMULH;
4744 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4745 MI.removeOperand(1);
4748 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4756 if (Opcode == TargetOpcode::G_SMULH) {
4757 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4758 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4765 case TargetOpcode::G_FNEG: {
4766 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4769 Register CastedSubByReg = SubByReg;
4771 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4772 !SubByRegTy.getScalarType().isInteger()) {
4773 auto BitcastDst = SubByRegTy.changeElementType(
4775 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4781 if (ResTy != TyInt) {
4783 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4786 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4788 MI.eraseFromParent();
4791 case TargetOpcode::G_FSUB:
4792 case TargetOpcode::G_STRICT_FSUB: {
4793 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4794 LLT Ty = MRI.getType(Res);
4799 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4800 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4804 MI.eraseFromParent();
4807 case TargetOpcode::G_FMAD:
4809 case TargetOpcode::G_FFLOOR:
4811 case TargetOpcode::G_LROUND:
4812 case TargetOpcode::G_LLROUND: {
4815 LLT SrcTy = MRI.getType(SrcReg);
4816 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4819 MI.eraseFromParent();
4822 case TargetOpcode::G_INTRINSIC_ROUND:
4824 case TargetOpcode::G_FRINT: {
4827 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4830 case TargetOpcode::G_INTRINSIC_LRINT:
4831 case TargetOpcode::G_INTRINSIC_LLRINT: {
4834 LLT SrcTy = MRI.getType(SrcReg);
4836 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4838 MI.eraseFromParent();
4841 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4842 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4843 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4844 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4845 **
MI.memoperands_begin());
4847 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4848 MI.eraseFromParent();
4851 case TargetOpcode::G_LOAD:
4852 case TargetOpcode::G_SEXTLOAD:
4853 case TargetOpcode::G_ZEXTLOAD:
4855 case TargetOpcode::G_STORE:
4857 case TargetOpcode::G_CTLZ_ZERO_POISON:
4858 case TargetOpcode::G_CTTZ_ZERO_POISON:
4859 case TargetOpcode::G_CTLZ:
4860 case TargetOpcode::G_CTTZ:
4861 case TargetOpcode::G_CTPOP:
4862 case TargetOpcode::G_CTLS:
4865 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4867 Register NewRes = MRI.cloneVirtualRegister(Res);
4874 MI.eraseFromParent();
4878 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4879 const LLT CondTy = MRI.getType(CarryOut);
4880 const LLT Ty = MRI.getType(Res);
4882 Register NewRes = MRI.cloneVirtualRegister(Res);
4885 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4891 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4892 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4899 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4904 MI.eraseFromParent();
4908 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4913 MI.eraseFromParent();
4917 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4918 const LLT CondTy = MRI.getType(BorrowOut);
4919 const LLT Ty = MRI.getType(Res);
4922 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4928 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4929 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4936 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4937 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4939 MI.eraseFromParent();
4979 case G_MERGE_VALUES:
4981 case G_UNMERGE_VALUES:
4983 case TargetOpcode::G_SEXT_INREG: {
4984 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4985 int64_t SizeInBits =
MI.getOperand(2).getImm();
4987 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4988 LLT DstTy = MRI.getType(DstReg);
4989 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4992 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4993 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4994 MI.eraseFromParent();
4997 case G_EXTRACT_VECTOR_ELT:
4998 case G_INSERT_VECTOR_ELT:
5000 case G_SHUFFLE_VECTOR:
5002 case G_VECTOR_COMPRESS:
5004 case G_DYN_STACKALLOC:
5006 case G_INSERT_SUBVECTOR: {
5007 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
5008 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
5013 Register Subvector =
MI.getOperand(2).getReg();
5014 auto InsertionPointImm =
MI.getOperand(3).getImm();
5017 LLT DstTy = MRI.getType(Subvector);
5021 bool InsertInLowHalf = InsertionPointImm == 0;
5022 auto Extract =
MIRBuilder.buildExtractSubvector(
5024 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
5026 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
5027 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
5029 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
5030 {LowHalf, HighHalf});
5031 MI.eraseFromParent();
5037 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
5038 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
5044 if (i >= InsertionPointImm &&
5046 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
5054 MI.eraseFromParent();
5058 case G_EXTRACT_SUBVECTOR: {
5061 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5063 LLT SrcTy = MRI.getType(SrcReg);
5064 LLT DstTy = MRI.getType(DstReg);
5066 if (SrcTy.isScalable())
5077 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5078 ExtractionPointImm + i)
5082 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5083 MI.eraseFromParent();
5088 case G_STACKRESTORE:
5098 case G_READ_REGISTER:
5099 case G_WRITE_REGISTER:
5106 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5107 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5113 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5118 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5125 case G_TRUNC_SSAT_S:
5126 case G_TRUNC_USAT_U:
5127 case G_TRUNC_SSAT_U:
5133 bool IsSigned =
MI.getOpcode() == G_ABDS;
5134 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5135 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5136 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5159 case G_MEMCPY_INLINE:
5160 case G_MEMSET_INLINE:
5172 case G_ATOMICRMW_SUB: {
5173 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5174 const LLT ValTy = MRI.getType(Val);
5178 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5179 MI.eraseFromParent();
5207 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5211 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5217 Align StackTypeAlign =
5224 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5225 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5230 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5242 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5245 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5256 "Converting bits to bytes lost precision");
5262 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5263 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5265 if (IdxTy != MRI.getType(Index))
5266 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5271 LLT PtrTy = MRI.getType(VecPtr);
5272 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5280 std::initializer_list<unsigned> NonVecOpIndices) {
5281 if (
MI.getNumMemOperands() != 0)
5284 LLT VecTy =
MRI.getType(
MI.getReg(0));
5289 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5298 if (!Ty.isVector()) {
5304 if (Ty.getNumElements() != NumElts)
5319 assert(Ty.isVector() &&
"Expected vector type");
5326 for (
int i = 0; i <
NumParts; ++i) {
5331 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5340 for (
unsigned i = 0; i <
N; ++i) {
5342 Ops.push_back(
Op.getReg());
5343 else if (
Op.isImm())
5344 Ops.push_back(
Op.getImm());
5345 else if (
Op.isPredicate())
5367 std::initializer_list<unsigned> NonVecOpIndices) {
5369 "Non-compatible opcode or not specified non-vector operands");
5370 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5372 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5373 unsigned NumDefs =
MI.getNumDefs();
5381 for (
unsigned i = 0; i < NumDefs; ++i) {
5382 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5390 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5391 ++UseIdx, ++UseNo) {
5394 MI.getOperand(UseIdx));
5403 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5407 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5409 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5410 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5413 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5414 Uses.push_back(InputOpsPieces[InputNo][i]);
5417 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5418 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5423 for (
unsigned i = 0; i < NumDefs; ++i)
5424 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5426 for (
unsigned i = 0; i < NumDefs; ++i)
5427 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5430 MI.eraseFromParent();
5437 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5439 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5440 unsigned NumDefs =
MI.getNumDefs();
5444 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5449 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5450 UseIdx += 2, ++UseNo) {
5458 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5460 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5461 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5463 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5466 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5467 Phi.addUse(InputOpsPieces[j][i]);
5468 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5478 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5480 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5483 MI.eraseFromParent();
5491 const int NumDst =
MI.getNumOperands() - 1;
5492 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5493 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5494 LLT SrcTy = MRI.getType(SrcReg);
5496 if (TypeIdx != 1 || NarrowTy == DstTy)
5503 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5506 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5520 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5521 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5522 const int PartsPerUnmerge = NumDst / NumUnmerge;
5524 for (
int I = 0;
I != NumUnmerge; ++
I) {
5525 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5527 for (
int J = 0; J != PartsPerUnmerge; ++J)
5528 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5529 MIB.addUse(Unmerge.getReg(
I));
5532 MI.eraseFromParent();
5539 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5543 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5545 if (NarrowTy == SrcTy)
5553 assert(SrcTy.isVector() &&
"Expected vector types");
5555 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5569 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5570 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5571 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5577 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5578 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5579 ++i,
Offset += NumNarrowTyElts) {
5582 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5585 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5586 MI.eraseFromParent();
5590 assert(TypeIdx == 0 &&
"Bad type index");
5591 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5607 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5609 for (
unsigned i = 0; i <
NumParts; ++i) {
5611 for (
unsigned j = 0; j < NumElts; ++j)
5612 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5614 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5617 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5618 MI.eraseFromParent();
5626 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5628 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5630 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5632 InsertVal =
MI.getOperand(2).getReg();
5634 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5635 LLT VecTy = MRI.getType(SrcVec);
5641 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5645 MI.eraseFromParent();
5654 SplitPieces[IdxVal] = InsertVal;
5655 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5657 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5661 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5664 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5665 TargetOpcode::G_ANYEXT);
5669 LLT IdxTy = MRI.getType(Idx);
5670 int64_t PartIdx = IdxVal / NewNumElts;
5672 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5675 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5678 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5679 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5680 VecParts[PartIdx] = InsertPart.getReg(0);
5684 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5686 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5690 MI.eraseFromParent();
5710 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5722 LLT ValTy = MRI.getType(ValReg);
5731 int NumLeftover = -1;
5737 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5740 NumLeftover = NarrowLeftoverRegs.
size();
5747 LLT PtrTy = MRI.getType(AddrReg);
5757 auto MMO = LdStMI.
getMMO();
5762 for (
unsigned Idx = 0, E =
NumParts; Idx != E &&
Offset < TotalSize;
5764 unsigned ByteOffset =
Offset / 8;
5767 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5774 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5775 ValRegs.push_back(Dst);
5776 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5778 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5787 unsigned HandledOffset =
5792 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5795 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5796 LeftoverTy, NarrowLeftoverRegs);
5810 switch (
MI.getOpcode()) {
5811 case G_IMPLICIT_DEF:
5827 case G_FCANONICALIZE:
5844 case G_INTRINSIC_LRINT:
5845 case G_INTRINSIC_LLRINT:
5846 case G_INTRINSIC_ROUND:
5847 case G_INTRINSIC_ROUNDEVEN:
5850 case G_INTRINSIC_TRUNC:
5878 case G_FMINNUM_IEEE:
5879 case G_FMAXNUM_IEEE:
5901 case G_CTLZ_ZERO_POISON:
5903 case G_CTTZ_ZERO_POISON:
5920 case G_ADDRSPACE_CAST:
5933 case G_STRICT_FLDEXP:
5935 case G_TRUNC_SSAT_S:
5936 case G_TRUNC_SSAT_U:
5937 case G_TRUNC_USAT_U:
5945 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5950 case G_UNMERGE_VALUES:
5952 case G_BUILD_VECTOR:
5953 assert(TypeIdx == 0 &&
"not a vector type index");
5955 case G_CONCAT_VECTORS:
5959 case G_EXTRACT_SUBVECTOR: {
5961 LLT DstTy = MRI.getType(DstReg);
5963 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5973 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5974 uint64_t RequiredSubvectorIndex =
5978 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5981 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5984 MI.eraseFromParent();
5987 case G_EXTRACT_VECTOR_ELT:
5988 case G_INSERT_VECTOR_ELT:
5997 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5998 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
6000 case G_SHUFFLE_VECTOR:
6006 case G_INTRINSIC_FPTRUNC_ROUND:
6016 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
6017 "Not a bitcast operation");
6022 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6024 unsigned NewElemCount =
6027 if (NewElemCount == 1) {
6030 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
6037 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
6046 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
6047 MI.eraseFromParent();
6053 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6057 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6058 MI.getFirst3RegLLTs();
6061 if (DstTy != Src1Ty)
6063 if (DstTy != Src2Ty)
6078 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6094 unsigned InputUsed[2] = {-1U, -1U};
6095 unsigned FirstMaskIdx =
High * NewElts;
6096 bool UseBuildVector =
false;
6097 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6099 int Idx = Mask[FirstMaskIdx + MaskOffset];
6104 if (
Input >= std::size(Inputs)) {
6111 Idx -=
Input * NewElts;
6115 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6116 if (InputUsed[OpNo] ==
Input) {
6119 }
else if (InputUsed[OpNo] == -1U) {
6121 InputUsed[OpNo] =
Input;
6126 if (OpNo >= std::size(InputUsed)) {
6129 UseBuildVector =
true;
6134 Ops.push_back(Idx + OpNo * NewElts);
6137 if (UseBuildVector) {
6142 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6144 int Idx = Mask[FirstMaskIdx + MaskOffset];
6149 if (
Input >= std::size(Inputs)) {
6156 Idx -=
Input * NewElts;
6160 .buildExtractVectorElement(
6161 EltTy, Inputs[
Input],
6167 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6168 }
else if (InputUsed[0] == -1U) {
6170 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6171 }
else if (NewElts == 1) {
6172 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6174 Register Op0 = Inputs[InputUsed[0]];
6178 : Inputs[InputUsed[1]];
6180 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6187 MI.eraseFromParent();
6200 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6206 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6211 : SrcTy.getNumElements();
6215 if (DstTy != NarrowTy)
6222 while (NumPartsLeft > 1) {
6223 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6226 .buildInstr(ScalarOpc, {NarrowTy},
6227 {SplitSrcs[Idx], SplitSrcs[Idx + 1]},
6231 SplitSrcs = PartialResults;
6232 PartialResults.
clear();
6233 NumPartsLeft = SplitSrcs.
size();
6237 MI.eraseFromParent();
6242 for (
unsigned Idx = 1; Idx <
NumParts; ++Idx)
6244 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]},
6248 MI.eraseFromParent();
6252 for (
unsigned Part = 0; Part <
NumParts; ++Part) {
6254 .buildInstr(RdxMI.getOpcode(), {DstTy},
6264 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6267 Register Acc = PartialReductions[0];
6268 for (
unsigned Part = 1; Part <
NumParts; ++Part) {
6270 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, {Acc, PartialReductions[Part]},
6274 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]},
6279 MI.eraseFromParent();
6285 unsigned int TypeIdx,
6287 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6288 MI.getFirst3RegLLTs();
6289 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6293 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6294 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6295 "Unexpected vecreduce opcode");
6296 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6297 ? TargetOpcode::G_FADD
6298 : TargetOpcode::G_FMUL;
6301 unsigned NumParts = SrcTy.getNumElements();
6304 for (
unsigned i = 0; i <
NumParts; i++)
6306 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]},
6311 MI.eraseFromParent();
6318 unsigned ScalarOpc) {
6326 while (SplitSrcs.
size() > 1) {
6328 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6338 SplitSrcs = std::move(PartialRdxs);
6342 MI.getOperand(1).setReg(SplitSrcs[0]);
6349 const LLT HalfTy,
const LLT AmtTy) {
6351 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6352 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6356 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6357 MI.eraseFromParent();
6363 unsigned VTBits = 2 * NVTBits;
6366 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6367 if (Amt.
ugt(VTBits)) {
6369 }
else if (Amt.
ugt(NVTBits)) {
6372 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6373 }
else if (Amt == NVTBits) {
6381 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6384 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6385 if (Amt.
ugt(VTBits)) {
6387 }
else if (Amt.
ugt(NVTBits)) {
6389 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6391 }
else if (Amt == NVTBits) {
6395 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6397 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6399 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6405 if (Amt.
ugt(VTBits)) {
6407 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6408 }
else if (Amt.
ugt(NVTBits)) {
6410 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6412 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6413 }
else if (Amt == NVTBits) {
6416 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6418 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6420 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6422 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6429 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6430 MI.eraseFromParent();
6446 LLT DstTy = MRI.getType(DstReg);
6451 LLT ShiftAmtTy = MRI.getType(Amt);
6453 if (DstEltSize % 2 != 0)
6480 const unsigned NewBitSize = DstEltSize / 2;
6492 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6494 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6495 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6498 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6499 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6501 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6506 switch (
MI.getOpcode()) {
6507 case TargetOpcode::G_SHL: {
6509 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6511 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6512 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6513 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6516 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6517 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6519 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6521 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6523 ResultRegs[0] =
Lo.getReg(0);
6524 ResultRegs[1] =
Hi.getReg(0);
6527 case TargetOpcode::G_LSHR:
6528 case TargetOpcode::G_ASHR: {
6530 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6532 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6533 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6534 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6538 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6541 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6542 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6544 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6548 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6550 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6552 ResultRegs[0] =
Lo.getReg(0);
6553 ResultRegs[1] =
Hi.getReg(0);
6560 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6561 MI.eraseFromParent();
6570 LLT TargetTy,
LLT ShiftAmtTy) {
6573 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6575 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6576 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6577 const bool NeedsInterWordShift = ShiftBits != 0;
6580 case TargetOpcode::G_SHL: {
6583 if (PartIdx < ShiftWords)
6586 unsigned SrcIdx = PartIdx - ShiftWords;
6587 if (!NeedsInterWordShift)
6588 return SrcParts[SrcIdx];
6593 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6597 return Hi.getReg(0);
6600 case TargetOpcode::G_LSHR: {
6601 unsigned SrcIdx = PartIdx + ShiftWords;
6604 if (!NeedsInterWordShift)
6605 return SrcParts[SrcIdx];
6610 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6614 return Lo.getReg(0);
6617 case TargetOpcode::G_ASHR: {
6619 unsigned SrcIdx = PartIdx + ShiftWords;
6622 if (!NeedsInterWordShift)
6623 return SrcParts[SrcIdx];
6654 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6655 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6660 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6669 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6670 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6672 auto IsZeroBitShift =
6680 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6681 : TargetOpcode::G_SHL;
6684 auto TargetBitsConst =
6686 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6691 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6696 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6698 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6702 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6715 LLT DstTy = MRI.getType(DstReg);
6719 const unsigned NumParts = DstBits / TargetBits;
6721 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6731 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6732 MI.eraseFromParent();
6737 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6738 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6744 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6748 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6751 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6752 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6758 Params, TargetTy, ShiftAmtTy);
6760 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6761 MI.eraseFromParent();
6770 LLT DstTy = MRI.getType(DstReg);
6771 LLT ShiftAmtTy = MRI.getType(AmtReg);
6775 const unsigned NumParts = DstBits / TargetBits;
6777 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6794 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6806 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6807 auto TargetBitsLog2Const =
6808 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6809 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6812 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6814 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6822 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6823 auto TargetBitsMinusOneConst =
6824 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6826 .buildAShr(TargetTy, SrcParts[
NumParts - 1],
6827 TargetBitsMinusOneConst)
6830 FillValue = ZeroReg;
6840 Register InBoundsResult = FillValue;
6851 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy,
K);
6853 WordShift, WordShiftKConst);
6865 switch (
MI.getOpcode()) {
6866 case TargetOpcode::G_SHL:
6867 MainSrcIdx = (int)
I - (
int)
K;
6868 CarrySrcIdx = MainSrcIdx - 1;
6870 case TargetOpcode::G_LSHR:
6871 case TargetOpcode::G_ASHR:
6872 MainSrcIdx = (int)
I + (
int)
K;
6873 CarrySrcIdx = MainSrcIdx + 1;
6881 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)
NumParts) {
6882 Register MainOp = SrcParts[MainSrcIdx];
6886 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)
NumParts)
6887 CarryOp = SrcParts[CarrySrcIdx];
6888 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6890 CarryOp = FillValue;
6896 ResultForK = FillValue;
6902 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6909 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6913 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6914 MI.eraseFromParent();
6921 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6924 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6939 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6944 "getNeutralElementForVecReduce called with invalid opcode!");
6945 case TargetOpcode::G_VECREDUCE_ADD:
6946 case TargetOpcode::G_VECREDUCE_OR:
6947 case TargetOpcode::G_VECREDUCE_XOR:
6948 case TargetOpcode::G_VECREDUCE_UMAX:
6950 case TargetOpcode::G_VECREDUCE_MUL:
6952 case TargetOpcode::G_VECREDUCE_AND:
6953 case TargetOpcode::G_VECREDUCE_UMIN:
6956 case TargetOpcode::G_VECREDUCE_SMAX:
6959 case TargetOpcode::G_VECREDUCE_SMIN:
6962 case TargetOpcode::G_VECREDUCE_FADD:
6964 case TargetOpcode::G_VECREDUCE_FMUL:
6966 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6967 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6968 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6969 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6977 unsigned Opc =
MI.getOpcode();
6979 case TargetOpcode::G_IMPLICIT_DEF:
6980 case TargetOpcode::G_LOAD: {
6988 case TargetOpcode::G_STORE:
6995 case TargetOpcode::G_AND:
6996 case TargetOpcode::G_OR:
6997 case TargetOpcode::G_XOR:
6998 case TargetOpcode::G_ADD:
6999 case TargetOpcode::G_SUB:
7000 case TargetOpcode::G_MUL:
7001 case TargetOpcode::G_FADD:
7002 case TargetOpcode::G_FSUB:
7003 case TargetOpcode::G_FMUL:
7004 case TargetOpcode::G_FDIV:
7005 case TargetOpcode::G_FCOPYSIGN:
7006 case TargetOpcode::G_UADDSAT:
7007 case TargetOpcode::G_USUBSAT:
7008 case TargetOpcode::G_SADDSAT:
7009 case TargetOpcode::G_SSUBSAT:
7010 case TargetOpcode::G_SMIN:
7011 case TargetOpcode::G_SMAX:
7012 case TargetOpcode::G_UMIN:
7013 case TargetOpcode::G_UMAX:
7014 case TargetOpcode::G_FMINNUM:
7015 case TargetOpcode::G_FMAXNUM:
7016 case TargetOpcode::G_FMINNUM_IEEE:
7017 case TargetOpcode::G_FMAXNUM_IEEE:
7018 case TargetOpcode::G_FMINIMUM:
7019 case TargetOpcode::G_FMAXIMUM:
7020 case TargetOpcode::G_FMINIMUMNUM:
7021 case TargetOpcode::G_FMAXIMUMNUM:
7022 case TargetOpcode::G_STRICT_FADD:
7023 case TargetOpcode::G_STRICT_FSUB:
7024 case TargetOpcode::G_STRICT_FMUL: {
7032 case TargetOpcode::G_SHL:
7033 case TargetOpcode::G_ASHR:
7034 case TargetOpcode::G_LSHR: {
7040 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
7046 case TargetOpcode::G_FMA:
7047 case TargetOpcode::G_STRICT_FMA:
7048 case TargetOpcode::G_FSHR:
7049 case TargetOpcode::G_FSHL: {
7058 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
7059 case TargetOpcode::G_EXTRACT:
7066 case TargetOpcode::G_INSERT:
7067 case TargetOpcode::G_INSERT_VECTOR_ELT:
7068 case TargetOpcode::G_FREEZE:
7069 case TargetOpcode::G_FNEG:
7070 case TargetOpcode::G_FABS:
7071 case TargetOpcode::G_FSQRT:
7072 case TargetOpcode::G_FCEIL:
7073 case TargetOpcode::G_FFLOOR:
7074 case TargetOpcode::G_FNEARBYINT:
7075 case TargetOpcode::G_FRINT:
7076 case TargetOpcode::G_INTRINSIC_ROUND:
7077 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7078 case TargetOpcode::G_INTRINSIC_TRUNC:
7079 case TargetOpcode::G_BITREVERSE:
7080 case TargetOpcode::G_BSWAP:
7081 case TargetOpcode::G_FCANONICALIZE:
7082 case TargetOpcode::G_SEXT_INREG:
7083 case TargetOpcode::G_ABS:
7084 case TargetOpcode::G_CTLZ:
7085 case TargetOpcode::G_CTPOP:
7093 case TargetOpcode::G_SELECT: {
7094 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7096 if (!CondTy.isScalar() ||
7102 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7104 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7109 if (CondTy.isVector())
7119 case TargetOpcode::G_UNMERGE_VALUES:
7121 case TargetOpcode::G_PHI:
7123 case TargetOpcode::G_SHUFFLE_VECTOR:
7125 case TargetOpcode::G_BUILD_VECTOR: {
7127 for (
auto Op :
MI.uses()) {
7135 MIRBuilder.buildDeleteTrailingVectorElements(
7136 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7137 MI.eraseFromParent();
7140 case TargetOpcode::G_SEXT:
7141 case TargetOpcode::G_ZEXT:
7142 case TargetOpcode::G_ANYEXT:
7143 case TargetOpcode::G_TRUNC:
7144 case TargetOpcode::G_FPTRUNC:
7145 case TargetOpcode::G_FPEXT:
7146 case TargetOpcode::G_FPTOSI:
7147 case TargetOpcode::G_FPTOUI:
7148 case TargetOpcode::G_FPTOSI_SAT:
7149 case TargetOpcode::G_FPTOUI_SAT:
7150 case TargetOpcode::G_SITOFP:
7151 case TargetOpcode::G_UITOFP:
7152 case TargetOpcode::G_TRUNC_SSAT_S:
7153 case TargetOpcode::G_TRUNC_SSAT_U:
7154 case TargetOpcode::G_TRUNC_USAT_U: {
7161 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7164 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7172 case TargetOpcode::G_ICMP:
7173 case TargetOpcode::G_FCMP: {
7181 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7186 case TargetOpcode::G_BITCAST: {
7190 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7191 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7207 case TargetOpcode::G_VECREDUCE_FADD:
7208 case TargetOpcode::G_VECREDUCE_FMUL:
7209 case TargetOpcode::G_VECREDUCE_ADD:
7210 case TargetOpcode::G_VECREDUCE_MUL:
7211 case TargetOpcode::G_VECREDUCE_AND:
7212 case TargetOpcode::G_VECREDUCE_OR:
7213 case TargetOpcode::G_VECREDUCE_XOR:
7214 case TargetOpcode::G_VECREDUCE_SMAX:
7215 case TargetOpcode::G_VECREDUCE_SMIN:
7216 case TargetOpcode::G_VECREDUCE_UMAX:
7217 case TargetOpcode::G_VECREDUCE_UMIN: {
7218 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7220 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7221 auto NeutralElement = getNeutralElementForVecReduce(
7227 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7228 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7229 NeutralElement, Idx);
7233 MO.
setReg(NewVec.getReg(0));
7245 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7247 unsigned MaskNumElts = Mask.size();
7248 unsigned SrcNumElts = SrcTy.getNumElements();
7251 if (MaskNumElts == SrcNumElts)
7254 if (MaskNumElts < SrcNumElts) {
7262 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7263 MI.getOperand(1).getReg(),
7264 MI.getOperand(2).getReg(), NewMask);
7265 MI.eraseFromParent();
7270 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7271 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7280 MOps1[0] =
MI.getOperand(1).getReg();
7281 MOps2[0] =
MI.getOperand(2).getReg();
7283 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7284 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7288 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7290 if (Idx >=
static_cast<int>(SrcNumElts))
7291 Idx += PaddedMaskNumElts - SrcNumElts;
7296 if (MaskNumElts != PaddedMaskNumElts) {
7298 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7301 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7303 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7308 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7311 MI.eraseFromParent();
7317 unsigned int TypeIdx,
LLT MoreTy) {
7318 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7320 unsigned NumElts = DstTy.getNumElements();
7323 if (DstTy.isVector() && Src1Ty.isVector() &&
7324 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7332 if (DstTy != Src1Ty || DstTy != Src2Ty)
7340 for (
unsigned I = 0;
I != NumElts; ++
I) {
7342 if (Idx <
static_cast<int>(NumElts))
7345 NewMask[
I] = Idx - NumElts + WidenNumElts;
7349 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7350 MI.getOperand(1).getReg(),
7351 MI.getOperand(2).getReg(), NewMask);
7352 MI.eraseFromParent();
7361 unsigned SrcParts = Src1Regs.
size();
7362 unsigned DstParts = DstRegs.
size();
7364 unsigned DstIdx = 0;
7366 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7367 DstRegs[DstIdx] = FactorSum;
7372 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7374 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7375 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7377 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7383 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7384 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7385 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7386 unsigned i = RevI - 1;
7388 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7398 if (DstIdx != DstParts - 1) {
7399 MachineInstrBuilder Uaddo =
7400 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7401 FactorSum = Uaddo.
getReg(0);
7402 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7403 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7404 MachineInstrBuilder Uaddo =
7405 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7406 FactorSum = Uaddo.
getReg(0);
7407 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7408 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7412 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7413 for (
unsigned i = 2; i < Factors.
size(); ++i)
7414 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7417 CarrySumPrevDstIdx = CarrySum;
7418 DstRegs[DstIdx] = FactorSum;
7430 LLT DstType = MRI.getType(DstReg);
7432 if (DstType.isVector())
7435 unsigned Opcode =
MI.getOpcode();
7436 unsigned OpO, OpE, OpF;
7438 case TargetOpcode::G_SADDO:
7439 case TargetOpcode::G_SADDE:
7440 case TargetOpcode::G_UADDO:
7441 case TargetOpcode::G_UADDE:
7442 case TargetOpcode::G_ADD:
7443 OpO = TargetOpcode::G_UADDO;
7444 OpE = TargetOpcode::G_UADDE;
7445 OpF = TargetOpcode::G_UADDE;
7446 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7447 OpF = TargetOpcode::G_SADDE;
7449 case TargetOpcode::G_SSUBO:
7450 case TargetOpcode::G_SSUBE:
7451 case TargetOpcode::G_USUBO:
7452 case TargetOpcode::G_USUBE:
7453 case TargetOpcode::G_SUB:
7454 OpO = TargetOpcode::G_USUBO;
7455 OpE = TargetOpcode::G_USUBE;
7456 OpF = TargetOpcode::G_USUBE;
7457 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7458 OpF = TargetOpcode::G_SSUBE;
7465 unsigned NumDefs =
MI.getNumExplicitDefs();
7466 Register Src1 =
MI.getOperand(NumDefs).getReg();
7467 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7470 CarryDst =
MI.getOperand(1).getReg();
7471 if (
MI.getNumOperands() == NumDefs + 3)
7472 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7474 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7475 LLT LeftoverTy, DummyTy;
7477 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7482 int NarrowParts = Src1Regs.
size();
7483 Src1Regs.
append(Src1Left);
7484 Src2Regs.
append(Src2Left);
7487 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7489 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7492 if (i == e - 1 && CarryDst)
7493 CarryOut = CarryDst;
7495 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7498 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7499 {Src1Regs[i], Src2Regs[i]});
7500 }
else if (i == e - 1) {
7501 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7502 {Src1Regs[i], Src2Regs[i], CarryIn});
7504 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7505 {Src1Regs[i], Src2Regs[i], CarryIn});
7511 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7512 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7513 ArrayRef(DstRegs).drop_front(NarrowParts));
7515 MI.eraseFromParent();
7521 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7523 LLT Ty = MRI.getType(DstReg);
7527 unsigned Size = Ty.getSizeInBits();
7529 if (
Size % NarrowSize != 0)
7533 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH ||
7534 MI.getOpcode() == TargetOpcode::G_SMULH;
7535 unsigned DstTmpParts =
NumParts * (IsMulHigh ? 2 : 1);
7541 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7546 if (
MI.getOpcode() == TargetOpcode::G_SMULH) {
7547 Register UnsignedHigh = MRI.createGenericVirtualRegister(Ty);
7548 MIRBuilder.buildMergeLikeInstr(UnsignedHigh, DstRegs);
7551 auto ShiftAmt =
MIRBuilder.buildConstant(NarrowTy, NarrowSize - 1);
7554 MIRBuilder.buildAShr(NarrowTy, Src1Parts.back(), ShiftAmt.getReg(0));
7556 MIRBuilder.buildAShr(NarrowTy, Src2Parts.back(), ShiftAmt.getReg(0));
7562 auto SignA =
MIRBuilder.buildMergeLikeInstr(Ty, SignAParts);
7563 auto SignB =
MIRBuilder.buildMergeLikeInstr(Ty, SignBParts);
7567 auto Ca =
MIRBuilder.buildAnd(Ty, SignA, Src2);
7568 auto Cb =
MIRBuilder.buildAnd(Ty, SignB, Src1);
7571 auto Tmp =
MIRBuilder.buildSub(Ty, UnsignedHigh, Ca);
7574 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7577 MI.eraseFromParent();
7587 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7590 LLT SrcTy = MRI.getType(Src);
7602 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7615 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7618 if (SizeOp1 % NarrowSize != 0)
7620 int NumParts = SizeOp1 / NarrowSize;
7627 uint64_t OpStart =
MI.getOperand(2).getImm();
7628 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7629 for (
int i = 0; i <
NumParts; ++i) {
7630 unsigned SrcStart = i * NarrowSize;
7632 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7635 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7643 int64_t ExtractOffset;
7645 if (OpStart < SrcStart) {
7647 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7649 ExtractOffset = OpStart - SrcStart;
7650 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7654 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7656 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7657 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7664 if (MRI.getType(DstReg).isVector())
7665 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7666 else if (DstRegs.
size() > 1)
7667 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7670 MI.eraseFromParent();
7682 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7684 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7687 SrcRegs.
append(LeftoverRegs);
7691 uint64_t OpStart =
MI.getOperand(3).getImm();
7692 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7693 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7694 unsigned DstStart =
I * NarrowSize;
7696 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7704 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7706 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7710 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7718 int64_t ExtractOffset, InsertOffset;
7720 if (OpStart < DstStart) {
7722 ExtractOffset = DstStart - OpStart;
7723 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7725 InsertOffset = OpStart - DstStart;
7727 SegSize = std::min(NarrowSize - InsertOffset, OpSize);
7731 if (ExtractOffset != 0 || SegSize != OpSize) {
7733 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7734 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7737 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7738 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7742 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7746 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7749 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7751 MI.eraseFromParent();
7759 LLT DstTy = MRI.getType(DstReg);
7761 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7767 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7768 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7772 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7773 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7776 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7777 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7778 {Src0Regs[I], Src1Regs[I]});
7782 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7785 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7786 DstLeftoverRegs.
push_back(Inst.getReg(0));
7789 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7790 LeftoverTy, DstLeftoverRegs);
7792 MI.eraseFromParent();
7802 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7804 LLT DstTy = MRI.getType(DstReg);
7809 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7810 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7811 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7813 MI.eraseFromParent();
7823 Register CondReg =
MI.getOperand(1).getReg();
7824 LLT CondTy = MRI.getType(CondReg);
7825 if (CondTy.isVector())
7829 LLT DstTy = MRI.getType(DstReg);
7835 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7836 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7840 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7841 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7844 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7846 CondReg, Src1Regs[
I], Src2Regs[
I]);
7850 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7852 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7856 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7857 LeftoverTy, DstLeftoverRegs);
7859 MI.eraseFromParent();
7869 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7872 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7873 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7876 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7878 auto C_0 =
B.buildConstant(NarrowTy, 0);
7880 UnmergeSrc.getReg(1), C_0);
7881 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7882 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7883 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7884 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7885 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7886 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7888 MI.eraseFromParent();
7901 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7904 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7905 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7908 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7910 auto C_0 =
B.buildConstant(NarrowTy, 0);
7912 UnmergeSrc.getReg(0), C_0);
7913 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7914 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7915 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7916 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7917 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7918 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7920 MI.eraseFromParent();
7933 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7936 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7941 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7945 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7946 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7954 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7955 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7958 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7959 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7961 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7963 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7965 MI.eraseFromParent();
7975 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7978 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7979 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7981 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7982 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7983 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7985 MI.eraseFromParent();
8000 LLT ExpTy = MRI.getType(ExpReg);
8005 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
8006 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
8007 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
8008 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
8010 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
8012 MI.getOperand(2).setReg(Trunc.getReg(0));
8019 unsigned Opc =
MI.getOpcode();
8022 auto QAction = LI.getAction(Q).Action;
8028 case TargetOpcode::G_CTLZ_ZERO_POISON: {
8031 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
8035 case TargetOpcode::G_CTLZ: {
8036 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8037 unsigned Len = SrcTy.getScalarSizeInBits();
8039 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
8041 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
8042 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
8045 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8046 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
8047 MI.eraseFromParent();
8063 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
8064 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
8067 Op = MIBOp.getReg(0);
8072 MI.eraseFromParent();
8075 case TargetOpcode::G_CTTZ_ZERO_POISON: {
8078 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
8082 case TargetOpcode::G_CTTZ: {
8083 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8085 unsigned Len = SrcTy.getScalarSizeInBits();
8086 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
8089 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
8090 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
8093 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8094 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
8095 MI.eraseFromParent();
8102 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8103 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8105 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8106 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8107 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8108 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8111 MI.eraseFromParent();
8115 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8116 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8120 case TargetOpcode::G_CTPOP: {
8122 LLT Ty = MRI.getType(SrcReg);
8123 unsigned Size = Ty.getScalarSizeInBits();
8135 auto C_1 =
B.buildConstant(Ty, 1);
8136 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8138 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8139 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8140 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8144 auto C_2 =
B.buildConstant(Ty, 2);
8145 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8147 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8148 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8149 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8150 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8157 auto C_4 =
B.buildConstant(Ty, 4);
8158 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8159 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8161 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8162 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8164 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8167 if (
Size == 16 && !Ty.isVector()) {
8169 auto C_8 =
B.buildConstant(Ty, 8);
8170 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8171 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8172 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8173 MI.eraseFromParent();
8182 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8184 auto IsMulSupported = [
this](
const LLT Ty) {
8185 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8188 if (IsMulSupported(Ty)) {
8189 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8190 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8192 auto ResTmp = B8Count;
8193 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8194 auto ShiftC =
B.buildConstant(Ty, Shift);
8195 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8196 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8198 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8200 MI.eraseFromParent();
8203 case TargetOpcode::G_CTLS: {
8204 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8208 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8209 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8211 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8217 MI.eraseFromParent();
8247 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8248 LLT Ty = MRI.getType(Dst);
8249 LLT ShTy = MRI.getType(Z);
8256 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8257 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8262 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8263 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8267 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8280 MI.eraseFromParent();
8286 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8287 LLT Ty = MRI.getType(Dst);
8288 LLT ShTy = MRI.getType(Z);
8291 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8305 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8306 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8307 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8308 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8309 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8315 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8318 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8321 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8323 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8324 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8325 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8328 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8330 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8332 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8335 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8336 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8341 MI.eraseFromParent();
8352 LLT Ty = MRI.getType(Dst);
8353 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8355 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8356 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8359 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8360 return lowerFunnelShiftAsShifts(
MI);
8364 if (Result == UnableToLegalize)
8365 return lowerFunnelShiftAsShifts(
MI);
8370 auto [Dst, Src] =
MI.getFirst2Regs();
8371 LLT DstTy = MRI.getType(Dst);
8372 LLT SrcTy = MRI.getType(Src);
8376 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8384 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8388 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8392 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8397 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8398 {UnmergeSrc.getReg(0)});
8399 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8400 {UnmergeSrc.getReg(1)});
8403 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8405 MI.eraseFromParent();
8422 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8426 LLT DstTy = MRI.getType(DstReg);
8427 LLT SrcTy = MRI.getType(SrcReg);
8435 SrcTy.getElementCount().divideCoefficientBy(2));
8448 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8460 MI.eraseFromParent();
8469 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8470 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8471 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8472 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8473 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8474 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8475 MI.eraseFromParent();
8480 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8482 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8483 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8488 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8489 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8491 return lowerRotateWithReverseRotate(
MI);
8494 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8495 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8496 bool IsFShLegal =
false;
8497 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8498 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8502 MI.eraseFromParent();
8507 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8510 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8515 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8516 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8517 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8528 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8529 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8531 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8538 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8539 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8541 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8543 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8547 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal, OrFlags);
8548 MI.eraseFromParent();
8556 auto [Dst, Src] =
MI.getFirst2Regs();
8561 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8574 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8576 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8581 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8583 MI.eraseFromParent();
8591 auto [Dst, Src] =
MI.getFirst2Regs();
8595 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8606 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8607 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8609 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8616 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8617 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8618 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8620 MI.eraseFromParent();
8631 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8632 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8638 MI.eraseFromParent();
8643 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8649 MI.eraseFromParent();
8653 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8673 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8683 MI.eraseFromParent();
8687 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8693 if (DstTy.getScalarSizeInBits() == 32) {
8700 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8701 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8703 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8710 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8711 MI.eraseFromParent();
8719 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8723 if (SrcTy !=
S64 && SrcTy !=
S32)
8725 if (DstTy !=
S32 && DstTy !=
S64)
8752 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8754 MI.eraseFromParent();
8759 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8764 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8771 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8773 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8774 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8776 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8777 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8779 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8781 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8782 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8783 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8786 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8787 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8788 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8790 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask,
K);
8793 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8798 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8799 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8805 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8807 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8808 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8810 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8815 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8816 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8818 MI.eraseFromParent();
8824 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8826 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8827 unsigned SatWidth = DstTy.getScalarSizeInBits();
8831 APInt MinInt, MaxInt;
8854 if (AreExactFloatBounds) {
8856 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8859 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8861 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8870 MI.eraseFromParent();
8875 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8880 MI.eraseFromParent();
8887 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8895 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8905 MI.eraseFromParent();
8911 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8915 MI.eraseFromParent();
8922 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8923 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8924 "Only G_FPEXT and G_FPTRUNC are expected");
8926 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8931 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8933 StoreOpc = TargetOpcode::G_STORE;
8934 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8937 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8938 LoadOpc = TargetOpcode::G_LOAD;
8947 StackTy, StackTyAlign);
8948 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8951 StackTy, StackTyAlign);
8952 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8954 MI.eraseFromParent();
8962 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8963 assert(SrcTy.getScalarType().isBFloat16() &&
8964 "expected a bf16 source for bf16 fpext lowering");
8975 if (DstTy.getScalarType().isFloat32())
8980 MI.eraseFromParent();
8985 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8986 if (SrcTy.getScalarType().isBFloat16() &&
8987 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8999 auto [Dst, Src] =
MI.getFirst2Regs();
9003 if (MRI.getType(Src).isVector())
9007 unsigned Flags =
MI.getFlags();
9010 MI.eraseFromParent();
9014 const unsigned ExpMask = 0x7ff;
9015 const unsigned ExpBiasf64 = 1023;
9016 const unsigned ExpBiasf16 = 15;
9018 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
9028 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
9035 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
9037 auto Zero =
MIRBuilder.buildConstant(I32, 0);
9039 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
9043 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
9045 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
9047 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
9048 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
9056 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
9057 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
9068 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9079 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9095 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9105 MI.eraseFromParent();
9112 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9120 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9146 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9148 MI.eraseFromParent();
9157 LLT OperandTy = MRI.getType(
Op);
9167 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9169 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9170 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9171 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9172 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9173 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9181 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9184 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9186 AbsWide, AbsNarrowAsWide);
9190 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9191 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9193 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9194 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9200 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9206 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9207 MI.eraseFromParent();
9213 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9214 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9217 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9220 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9227 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9228 LLT Ty = MRI.getType(Dst);
9230 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9231 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9232 MI.eraseFromParent();
9237 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9238 LLT Ty = MRI.getType(Src);
9239 auto Flags =
MI.getFlags();
9247 FracToUse = FracPart.getReg(0);
9249 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9253 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9255 FracToUse =
Select.getReg(0);
9258 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9261 MI.eraseFromParent();
9267 case TargetOpcode::G_SMIN:
9269 case TargetOpcode::G_SMAX:
9271 case TargetOpcode::G_UMIN:
9273 case TargetOpcode::G_UMAX:
9281 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9286 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9287 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9289 MI.eraseFromParent();
9298 LLT DstTy = MRI.getType(Dst);
9299 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9309 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9310 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9312 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9315 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9316 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9317 if (TLI.preferSelectsOverBooleanArithmetic(
9320 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9321 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9323 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9324 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9330 unsigned BoolExtOp =
9332 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9333 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9337 MI.eraseFromParent();
9343 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9344 const int Src0Size = Src0Ty.getScalarSizeInBits();
9345 const int Src1Size = Src1Ty.getScalarSizeInBits();
9355 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9356 Src0Ty.getScalarType().isInteger()))
9357 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9359 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9360 Src1Ty.getScalarType().isInteger()))
9361 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9366 auto NotSignBitMask =
MIRBuilder.buildConstant(
9370 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9372 if (Src0Ty == Src1Ty) {
9373 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9374 }
else if (Src0Size > Src1Size) {
9375 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9376 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9377 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9378 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9380 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9381 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9382 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9383 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9389 unsigned Flags =
MI.getFlags();
9394 if (DstTy == DstIntTy)
9395 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9401 MI.eraseFromParent();
9412 switch (
MI.getOpcode()) {
9413 case TargetOpcode::G_FMINNUM:
9414 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9416 case TargetOpcode::G_FMINIMUMNUM:
9417 NewOp = TargetOpcode::G_FMINNUM;
9419 case TargetOpcode::G_FMAXNUM:
9420 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9422 case TargetOpcode::G_FMAXIMUMNUM:
9423 NewOp = TargetOpcode::G_FMAXNUM;
9429 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9430 LLT Ty = MRI.getType(Dst);
9439 if (!VT->isKnownNeverSNaN(Src0))
9440 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9442 if (!VT->isKnownNeverSNaN(Src1))
9443 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9448 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9449 MI.eraseFromParent();
9455 unsigned Opc =
MI.getOpcode();
9456 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9457 LLT Ty = MRI.getType(Dst);
9460 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9462 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9463 unsigned OpcNonIeee =
9464 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9465 bool MinMaxMustRespectOrderedZero =
false;
9469 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9471 MinMaxMustRespectOrderedZero =
true;
9472 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9477 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9482 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9485 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9489 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9491 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9503 const unsigned Flags =
MI.getFlags();
9509 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9511 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9513 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9515 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9517 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9522 MI.eraseFromParent();
9529 LLT Ty = MRI.getType(DstReg);
9530 unsigned Flags =
MI.getFlags();
9535 MI.eraseFromParent();
9541 auto [DstReg,
X] =
MI.getFirst2Regs();
9542 const unsigned Flags =
MI.getFlags();
9543 const LLT Ty = MRI.getType(DstReg);
9555 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9557 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9562 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9563 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9564 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9565 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9567 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9569 MI.eraseFromParent();
9574 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9575 unsigned Flags =
MI.getFlags();
9576 LLT Ty = MRI.getType(DstReg);
9583 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9584 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9587 SrcReg, Zero, Flags);
9589 SrcReg, Trunc, Flags);
9593 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9594 MI.eraseFromParent();
9600 const unsigned NumOps =
MI.getNumOperands();
9601 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9602 unsigned PartSize = Src0Ty.getSizeInBits();
9607 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9608 const unsigned Offset = (
I - 1) * PartSize;
9611 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9614 MRI.createGenericVirtualRegister(WideTy);
9617 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9618 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9619 ResultReg = NextResult;
9622 if (DstTy.isPointer()) {
9623 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9624 DstTy.getAddressSpace())) {
9630 }
else if (WideTy != DstTy) {
9634 MI.eraseFromParent();
9640 const unsigned NumDst =
MI.getNumOperands() - 1;
9641 Register SrcReg =
MI.getOperand(NumDst).getReg();
9642 Register Dst0Reg =
MI.getOperand(0).getReg();
9643 LLT DstTy = MRI.getType(Dst0Reg);
9652 LLT IntTy = MRI.getType(SrcReg);
9657 unsigned Offset = DstSize;
9658 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9660 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9664 MI.eraseFromParent();
9683 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9684 InsertVal =
MI.getOperand(2).getReg();
9686 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9688 LLT VecTy = MRI.getType(SrcVec);
9698 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9699 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9701 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9704 MI.eraseFromParent();
9709 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9720 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9727 int64_t
Offset = IdxVal * EltBytes;
9738 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9741 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9743 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9746 MI.eraseFromParent();
9752 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9753 MI.getFirst3RegLLTs();
9763 for (
int Idx : Mask) {
9765 if (!
Undef.isValid())
9771 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9773 int NumElts = Src0Ty.getNumElements();
9774 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9775 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9776 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9778 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9780 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9785 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9786 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9787 MI.eraseFromParent();
9793 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9794 MI.getFirst4RegLLTs();
9796 if (VecTy.isScalableVector())
9812 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9817 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9820 std::optional<APInt> PassthruSplatVal =
9823 if (PassthruSplatVal.has_value()) {
9825 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9826 }
else if (HasPassthru) {
9827 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9828 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9834 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9838 unsigned NumElmts = VecTy.getNumElements();
9839 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9841 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9844 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9847 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9852 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9854 if (HasPassthru &&
I == NumElmts - 1) {
9857 auto AllLanesSelected =
MIRBuilder.buildICmp(
9859 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9860 {OutPos, EndOfVector});
9864 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9866 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9871 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9873 MI.eraseFromParent();
9890 if (Alignment >
Align(1)) {
9891 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9902 const auto &MF = *
MI.getMF();
9908 Register AllocSize =
MI.getOperand(1).getReg();
9911 LLT PtrTy = MRI.getType(Dst);
9912 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9919 MI.eraseFromParent();
9925 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9930 MI.eraseFromParent();
9936 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9941 MI.eraseFromParent();
9947 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9948 unsigned Offset =
MI.getOperand(2).getImm();
9951 if (SrcTy.isVector()) {
9952 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9953 unsigned DstSize = DstTy.getSizeInBits();
9955 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9956 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9958 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9962 for (
unsigned Idx =
Offset / SrcEltSize;
9963 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9964 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9966 if (SubVectorElts.
size() == 1)
9967 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9969 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9971 MI.eraseFromParent();
9977 if ((SrcTy.isPointer() &&
9978 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9979 (DstTy.isPointer() &&
9980 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9981 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9985 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9986 (SrcTy.isScalar() || SrcTy.isPointer() ||
9987 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9988 LLT SrcIntTy = SrcTy;
9989 if (!SrcTy.isScalar()) {
9991 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9995 if (DstTy.isPointer())
9997 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
10003 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
10007 if (DstTy.isPointer())
10008 MIRBuilder.buildIntToPtr(DstReg, ResultReg);
10010 MI.eraseFromParent();
10018 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
10019 uint64_t
Offset =
MI.getOperand(3).getImm();
10021 LLT DstTy = MRI.getType(Src);
10022 LLT InsertTy = MRI.getType(InsertSrc);
10025 bool IsNonIntegralInsert =
10035 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
10036 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10043 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
10045 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
10049 for (; Idx <
Offset / EltSize; ++Idx) {
10050 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10055 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
10056 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
10058 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
10062 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
10064 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
10071 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10074 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
10075 MI.eraseFromParent();
10084 if (IsNonIntegralDst || IsNonIntegralInsert) {
10085 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10089 LLT IntDstTy = DstTy;
10093 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
10098 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
10104 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10110 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10111 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10112 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10115 MI.eraseFromParent();
10121 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10122 MI.getFirst4RegLLTs();
10123 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10126 LLT BoolTy = Dst1Ty;
10128 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10137 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10143 auto ResultLowerThanLHS =
10147 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10151 auto LHSLessThanRHS =
10153 auto ResultNegative =
10155 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10159 MI.eraseFromParent();
10165 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10166 const LLT Ty = MRI.getType(Res);
10169 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10170 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10171 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10175 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10176 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10179 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10182 MI.eraseFromParent();
10187 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10188 const LLT Ty = MRI.getType(Res);
10191 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10192 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10193 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10197 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10198 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10200 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10203 MI.eraseFromParent();
10209 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10210 LLT Ty = MRI.getType(Res);
10214 switch (
MI.getOpcode()) {
10217 case TargetOpcode::G_UADDSAT:
10220 BaseOp = TargetOpcode::G_ADD;
10222 case TargetOpcode::G_SADDSAT:
10225 BaseOp = TargetOpcode::G_ADD;
10227 case TargetOpcode::G_USUBSAT:
10230 BaseOp = TargetOpcode::G_SUB;
10232 case TargetOpcode::G_SSUBSAT:
10235 BaseOp = TargetOpcode::G_SUB;
10250 uint64_t NumBits = Ty.getScalarSizeInBits();
10257 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10261 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10269 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10274 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10275 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10278 MI.eraseFromParent();
10284 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10285 LLT Ty = MRI.getType(Res);
10289 unsigned OverflowOp;
10290 switch (
MI.getOpcode()) {
10293 case TargetOpcode::G_UADDSAT:
10296 OverflowOp = TargetOpcode::G_UADDO;
10298 case TargetOpcode::G_SADDSAT:
10301 OverflowOp = TargetOpcode::G_SADDO;
10303 case TargetOpcode::G_USUBSAT:
10306 OverflowOp = TargetOpcode::G_USUBO;
10308 case TargetOpcode::G_SSUBSAT:
10311 OverflowOp = TargetOpcode::G_SSUBO;
10316 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10317 Register Tmp = OverflowRes.getReg(0);
10318 Register Ov = OverflowRes.getReg(1);
10327 uint64_t NumBits = Ty.getScalarSizeInBits();
10328 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10329 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10332 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10340 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10342 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10344 MI.eraseFromParent();
10350 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10351 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10352 "Expected shlsat opcode!");
10353 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10354 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10355 LLT Ty = MRI.getType(Res);
10359 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10360 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10369 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10374 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10376 MI.eraseFromParent();
10382 unsigned Opc =
MI.getOpcode();
10383 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10384 unsigned DstSize = DstTy.getScalarSizeInBits();
10385 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10387 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10390 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10393 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10394 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10397 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10398 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10401 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10403 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10409 MI.eraseFromParent();
10414 auto [Dst, Src] =
MI.getFirst2Regs();
10415 const LLT Ty = MRI.getType(Src);
10416 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10417 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10420 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10421 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10422 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10423 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10426 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10429 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10430 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10432 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10433 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10434 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10436 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10437 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10438 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10440 Res.getInstr()->getOperand(0).setReg(Dst);
10442 MI.eraseFromParent();
10449 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10452 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10453 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10454 return B.buildOr(Dst,
LHS,
RHS);
10459 auto [Dst, Src] =
MI.getFirst2Regs();
10460 const LLT SrcTy = MRI.getType(Src);
10461 unsigned Size = SrcTy.getScalarSizeInBits();
10462 unsigned VSize = SrcTy.getSizeInBits();
10465 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10466 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10467 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10468 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10473 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10474 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10475 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10479 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10502 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10506 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10509 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10513 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10517 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10522 MI.eraseFromParent();
10530 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10531 int NameOpIdx = IsRead ? 1 : 0;
10532 int ValRegIndex = IsRead ? 0 : 1;
10534 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10535 const LLT Ty = MRI.getType(ValReg);
10537 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10544 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10545 Fn,
MI.getDebugLoc()));
10549 MI.eraseFromParent();
10558 MI.eraseFromParent();
10564 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10565 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10566 Register Result =
MI.getOperand(0).getReg();
10567 LLT OrigTy = MRI.getType(Result);
10571 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10572 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10574 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10576 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10577 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10580 MI.eraseFromParent();
10586 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10591 MI.eraseFromParent();
10596 MI.eraseFromParent();
10603 unsigned BitSize = SrcTy.getScalarSizeInBits();
10607 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10614 APInt ExpMask = Inf;
10616 APInt QNaNBitMask =
10620 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10621 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10622 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10623 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10624 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10626 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10630 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10632 LLT DstTyCopy = DstTy;
10634 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10662 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10665 Mask &= ~PartialCheck;
10674 else if (PartialCheck ==
fcZero)
10686 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10687 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10688 auto SubnormalRes =
10690 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10692 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10693 appendToRes(SubnormalRes);
10700 else if (PartialCheck ==
fcInf)
10705 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10712 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10713 if (PartialCheck ==
fcNan) {
10717 }
else if (PartialCheck ==
fcQNan) {
10727 Abs, InfWithQnanBitC);
10728 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10735 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10737 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10738 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10741 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10743 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10746 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10747 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10749 appendToRes(NormalRes);
10753 MI.eraseFromParent();
10759 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10760 MI.getFirst4RegLLTs();
10769 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10770 Op1Ty = MRI.getType(Op1Reg);
10771 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10772 Op2Ty = MRI.getType(Op2Reg);
10776 if (MaskTy.isScalar()) {
10784 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10787 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10789 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10791 if (DstTy.isVector()) {
10793 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10794 MaskReg = ShufSplat.getReg(0);
10798 }
else if (!DstTy.isVector()) {
10803 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10807 if (!Op1Ty.getScalarType().isAnyScalar() &&
10808 !Op1Ty.getScalarType().isInteger())
10809 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10811 if (!Op2Ty.getScalarType().isAnyScalar() &&
10812 !Op2Ty.getScalarType().isInteger()) {
10814 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10815 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10818 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10819 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10820 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10825 if (DstTy == Op1TyInt)
10828 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10832 MI.eraseFromParent();
10838 unsigned Opcode =
MI.getOpcode();
10841 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10842 : TargetOpcode::G_UDIV,
10843 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10845 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10846 : TargetOpcode::G_UREM,
10847 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10848 MI.eraseFromParent();
10858 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10862 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10865 MI.eraseFromParent();
10875 Register SrcReg =
MI.getOperand(1).getReg();
10876 LLT Ty = MRI.getType(SrcReg);
10877 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10880 MI.eraseFromParent();
10886 Register SrcReg =
MI.getOperand(1).getReg();
10887 Register DestReg =
MI.getOperand(0).getReg();
10889 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10890 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10893 MI.eraseFromParent();
10899 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10900 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10901 "Expected G_ABDS or G_ABDU instruction");
10903 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10904 LLT Ty = MRI.getType(LHS);
10914 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10916 MI.eraseFromParent();
10922 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10923 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10924 "Expected G_ABDS or G_ABDU instruction");
10926 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10927 LLT Ty = MRI.getType(LHS);
10932 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10933 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10934 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10936 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10937 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10939 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10941 MI.eraseFromParent();
10946 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10951 if (!(SrcTy.getScalarType().isAnyScalar() ||
10952 SrcTy.getScalarType().isInteger())) {
10954 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10955 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10958 if (MRI.getType(DstReg) != TyInt) {
10962 .buildAnd(TyInt, CastedSrc,
10965 DstTy.getScalarSizeInBits())))
10977 MI.eraseFromParent();
10983 Register SrcReg =
MI.getOperand(1).getReg();
10984 LLT SrcTy = MRI.getType(SrcReg);
10985 LLT DstTy = MRI.getType(SrcReg);
10988 if (SrcTy.isScalar()) {
10993 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
11004 Register ListPtr =
MI.getOperand(1).getReg();
11005 LLT PtrTy = MRI.getType(ListPtr);
11012 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
11014 const Align A(
MI.getOperand(2).getImm());
11016 if (
A > TLI.getMinStackArgumentAlignment()) {
11018 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
11019 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
11020 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
11021 VAList = AndDst.getReg(0);
11028 LLT LLTTy = MRI.getType(Dst);
11031 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
11032 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
11037 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
11039 Align EltAlignment =
DL.getABITypeAlign(Ty);
11042 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
11044 MI.eraseFromParent();
11049 unsigned OpCode =
MI.getOpcode();
11050 assert((OpCode == TargetOpcode::G_SMULFIX ||
11051 OpCode == TargetOpcode::G_UMULFIX ||
11052 OpCode == TargetOpcode::G_SMULFIXSAT ||
11053 OpCode == TargetOpcode::G_UMULFIXSAT) &&
11054 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
11055 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
11056 LLT Ty = MRI.getType(Dst);
11057 unsigned Scale =
MI.getOperand(3).getImm();
11059 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
11060 OpCode == TargetOpcode::G_UMULFIXSAT);
11061 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
11062 OpCode == TargetOpcode::G_SMULFIXSAT);
11064 if (!Saturating && Scale == 0) {
11066 MI.eraseFromParent();
11072 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
11095 MI.eraseFromParent();
11102 unsigned NumBits = Ty.getScalarSizeInBits();
11104 if (!Ty.isVector() && ValVRegAndVal) {
11105 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
11113 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11136 auto &MF = *
MI.getParent()->getParent();
11141 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11142 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11145 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11146 const auto &DstMMO = **
MI.memoperands_begin();
11148 if (DstAlignCanChange) {
11151 Align NewAlign =
DL.getABITypeAlign(IRTy);
11152 if (NewAlign > Alignment) {
11161 MachineIRBuilder MIB(
MI);
11163 LLT LargestTy = MemOps[0];
11164 for (
unsigned i = 1; i < MemOps.
size(); i++)
11166 LargestTy = MemOps[i];
11178 LLT PtrTy = MRI.getType(Dst);
11179 unsigned DstOff = 0;
11180 unsigned Size = KnownLen;
11181 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11182 LLT Ty = MemOps[
I];
11185 if (TySize >
Size) {
11189 DstOff -= TySize -
Size;
11199 TLI.isTruncateFree(LargestVT, VT))
11200 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11213 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11216 MIB.buildStore(
Value, Ptr, *StoreMMO);
11221 MI.eraseFromParent();
11229 auto &MF = *
MI.getParent()->getParent();
11233 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11234 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11237 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11243 const auto &DstMMO = **
MI.memoperands_begin();
11244 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11246 if (DstAlignCanChange) {
11249 Align NewAlign =
DL.getABITypeAlign(IRTy);
11254 if (!
TRI->hasStackRealignment(MF))
11255 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11256 NewAlign = std::min(NewAlign, *StackAlign);
11258 if (NewAlign > Alignment) {
11267 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11269 MachineIRBuilder MIB(
MI);
11275 LLT SrcTy = MRI.getType(Src);
11276 LLT DstTy = MRI.getType(Dst);
11279 unsigned CurrOffset = 0;
11280 unsigned Size = KnownLen;
11281 for (
auto CopyTy : MemOps) {
11282 TypeSize TySize = CopyTy.getSizeInBytes();
11286 if (TySize >
Size) {
11287 unsigned Overlap = TySize -
Size;
11288 assert(Overlap < CurrOffset &&
11289 "overlapping memcpy load/store spans the whole region or more");
11290 CurrOffset -= Overlap;
11300 if (CurrOffset != 0) {
11302 MIB.buildConstant(
LLT::integer(SrcIndexSize), CurrOffset).getReg(0);
11303 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11305 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11309 if (CurrOffset != 0) {
11310 if (SrcIndexSize != DstIndexSize) {
11312 MIB.buildConstant(
LLT::integer(DstIndexSize), CurrOffset).getReg(0);
11314 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11316 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11317 CurrOffset += TySize;
11321 MI.eraseFromParent();
11329 auto &MF = *
MI.getParent()->getParent();
11333 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11334 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11337 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11338 const auto &DstMMO = **
MI.memoperands_begin();
11339 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11341 if (DstAlignCanChange) {
11344 Align NewAlign =
DL.getABITypeAlign(IRTy);
11349 if (!
TRI->hasStackRealignment(MF))
11350 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11351 NewAlign = std::min(NewAlign, *StackAlign);
11353 if (NewAlign > Alignment) {
11362 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11364 MachineIRBuilder MIB(
MI);
11368 unsigned CurrOffset = 0;
11369 unsigned Size = KnownLen;
11370 SmallVector<Register, 16> LoadVals;
11371 for (
auto CopyTy : MemOps) {
11372 TypeSize TySize = CopyTy.getSizeInBytes();
11376 if (TySize >
Size) {
11377 unsigned Overlap = TySize -
Size;
11378 assert(Overlap < CurrOffset &&
11379 "overlapping memmove load spans the whole region or more");
11380 CurrOffset -= Overlap;
11388 if (CurrOffset != 0) {
11389 LLT SrcTy = MRI.getType(Src);
11392 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11394 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11395 CurrOffset += TySize;
11401 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11402 LLT CopyTy = MemOps[
I];
11407 if (TySize >
Size) {
11408 unsigned Overlap = TySize -
Size;
11409 assert(Overlap < CurrOffset &&
11410 "overlapping memmove store spans the whole region or more");
11411 CurrOffset -= Overlap;
11418 if (CurrOffset != 0) {
11419 LLT DstTy = MRI.getType(Dst);
11422 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11424 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11425 CurrOffset += TySize;
11428 MI.eraseFromParent();
11435 const unsigned Opc =
MI.getOpcode();
11436 assert((
Opc == TargetOpcode::G_MEMCPY ||
11437 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11438 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11439 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11440 "Expected memcpy like instruction");
11442 if (KnownLen == 0) {
11443 MI.eraseFromParent();
11447 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11448 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11451 if (
Opc == TargetOpcode::G_MEMMOVE)
11452 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11454 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11455 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11465 bool DstAlignCanChange;
11466 std::vector<LLT> MemOps;
11468 DstAlignCanChange, MemOps))
const TargetLowering & TLI
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 isNonZeroModBitWidth(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
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
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
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,...
ConstantFP - Floating Point Values [float, double].
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.
bool isKnownNever(FPClassMask Mask) const
Return true if it's known this can never be one of the mask entries.
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,...
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.
@ Bitcast
Build the immediate as a bitcast of an integer constant with the same bits.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
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.
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.