44#define DEBUG_TYPE "legalizer"
57static std::pair<int, int>
63 unsigned NumParts =
Size / NarrowSize;
64 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
67 if (LeftoverSize == 0)
72 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
130 auto Step = LI.getAction(
MI, MRI);
131 switch (Step.Action) {
146 return bitcast(
MI, Step.TypeIdx, Step.NewType);
149 return lower(
MI, Step.TypeIdx, Step.NewType);
158 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
166void LegalizerHelper::insertParts(
Register DstReg,
188 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
190 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
191 return mergeMixedSubvectors(DstReg, AllRegs);
197 extractGCDType(GCDRegs, GCDTy, PartReg);
198 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
199 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
204 LLT Ty = MRI.getType(
Reg);
212void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
215 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
216 appendVectorElts(AllElts, PartRegs[i]);
219 if (!MRI.getType(Leftover).isVector())
222 appendVectorElts(AllElts, Leftover);
224 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
230 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
232 const int StartIdx = Regs.
size();
233 const int NumResults =
MI.getNumOperands() - 1;
235 for (
int I = 0;
I != NumResults; ++
I)
236 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
241 LLT SrcTy = MRI.getType(SrcReg);
242 if (SrcTy == GCDTy) {
248 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
255 LLT SrcTy = MRI.getType(SrcReg);
257 extractGCDType(Parts, GCDTy, SrcReg);
261LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
263 unsigned PadStrategy) {
268 int NumOrigSrc = VRegs.
size();
274 if (NumOrigSrc < NumParts * NumSubParts) {
275 if (PadStrategy == TargetOpcode::G_ZEXT)
276 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
277 else if (PadStrategy == TargetOpcode::G_ANYEXT)
278 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
280 assert(PadStrategy == TargetOpcode::G_SEXT);
285 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
301 for (
int I = 0;
I != NumParts; ++
I) {
302 bool AllMergePartsArePadding =
true;
305 for (
int J = 0; J != NumSubParts; ++J) {
306 int Idx =
I * NumSubParts + J;
307 if (Idx >= NumOrigSrc) {
308 SubMerge[J] = PadReg;
312 SubMerge[J] = VRegs[
Idx];
315 AllMergePartsArePadding =
false;
321 if (AllMergePartsArePadding && !AllPadReg) {
322 if (PadStrategy == TargetOpcode::G_ANYEXT)
323 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
324 else if (PadStrategy == TargetOpcode::G_ZEXT)
325 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
334 Remerge[
I] = AllPadReg;
338 if (NumSubParts == 1)
339 Remerge[
I] = SubMerge[0];
341 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
344 if (AllMergePartsArePadding && !AllPadReg)
345 AllPadReg = Remerge[
I];
348 VRegs = std::move(Remerge);
352void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
354 LLT DstTy = MRI.getType(DstReg);
359 if (DstTy == LCMTy) {
360 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
364 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
373 UnmergeDefs[0] = DstReg;
374 for (
unsigned I = 1;
I != NumDefs; ++
I)
375 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
378 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
386#define RTLIBCASE_INT(LibcallPrefix) \
390 return RTLIB::LibcallPrefix##32; \
392 return RTLIB::LibcallPrefix##64; \
394 return RTLIB::LibcallPrefix##128; \
396 llvm_unreachable("unexpected size"); \
400#define RTLIBCASE(LibcallPrefix) \
404 return RTLIB::LibcallPrefix##32; \
406 return RTLIB::LibcallPrefix##64; \
408 return RTLIB::LibcallPrefix##80; \
410 return RTLIB::LibcallPrefix##128; \
412 llvm_unreachable("unexpected size"); \
417 case TargetOpcode::G_LROUND:
419 case TargetOpcode::G_LLROUND:
421 case TargetOpcode::G_MUL:
423 case TargetOpcode::G_SDIV:
425 case TargetOpcode::G_UDIV:
427 case TargetOpcode::G_SREM:
429 case TargetOpcode::G_UREM:
431 case TargetOpcode::G_CTLZ_ZERO_POISON:
433 case TargetOpcode::G_FADD:
435 case TargetOpcode::G_FSUB:
437 case TargetOpcode::G_FMUL:
439 case TargetOpcode::G_FDIV:
441 case TargetOpcode::G_FEXP:
443 case TargetOpcode::G_FEXP2:
445 case TargetOpcode::G_FEXP10:
447 case TargetOpcode::G_FREM:
449 case TargetOpcode::G_FPOW:
451 case TargetOpcode::G_FPOWI:
453 case TargetOpcode::G_FMA:
455 case TargetOpcode::G_FSIN:
457 case TargetOpcode::G_FCOS:
459 case TargetOpcode::G_FTAN:
461 case TargetOpcode::G_FASIN:
463 case TargetOpcode::G_FACOS:
465 case TargetOpcode::G_FATAN:
467 case TargetOpcode::G_FATAN2:
469 case TargetOpcode::G_FSINH:
471 case TargetOpcode::G_FCOSH:
473 case TargetOpcode::G_FTANH:
475 case TargetOpcode::G_FSINCOS:
477 case TargetOpcode::G_FMODF:
479 case TargetOpcode::G_FLOG10:
481 case TargetOpcode::G_FLOG:
483 case TargetOpcode::G_FLOG2:
485 case TargetOpcode::G_FLDEXP:
487 case TargetOpcode::G_FCEIL:
489 case TargetOpcode::G_FFLOOR:
491 case TargetOpcode::G_FMINNUM:
493 case TargetOpcode::G_FMAXNUM:
495 case TargetOpcode::G_FMINIMUMNUM:
497 case TargetOpcode::G_FMAXIMUMNUM:
499 case TargetOpcode::G_FSQRT:
501 case TargetOpcode::G_FRINT:
503 case TargetOpcode::G_FNEARBYINT:
505 case TargetOpcode::G_INTRINSIC_TRUNC:
507 case TargetOpcode::G_INTRINSIC_ROUND:
509 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
511 case TargetOpcode::G_INTRINSIC_LRINT:
513 case TargetOpcode::G_INTRINSIC_LLRINT:
525 Attribute::SwiftError);
541 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
542 .removeAttribute(Attribute::NoAlias)
543 .removeAttribute(Attribute::NonNull)
548 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
549 CallerAttrs.hasRetAttr(Attribute::SExt))
553 if (
F.getFnAttribute(
"disable-tail-calls").getValueAsBool())
564 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
571 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
579 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
582 if (Ret->getNumImplicitOperands() != 1)
585 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
602 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
607 Info.OrigRet = Result;
610 (Result.Ty->isVoidTy() ||
611 Result.Ty ==
MIRBuilder.getMF().getFunction().getReturnType()) &&
622 if (
MI && Info.LoweredTailCall) {
623 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
633 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
634 "Expected instr following MI to be return or debug inst?");
637 Next->eraseFromParent();
638 }
while (
MI->getNextNode());
653 RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(
Libcall);
654 if (LibcallImpl == RTLIB::Unsupported)
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;
1590 for (
int i = 0; i < NumParts; ++i)
1594 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1596 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1597 MI.eraseFromParent();
1600 case TargetOpcode::G_CONSTANT: {
1601 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1602 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1603 unsigned TotalSize = Ty.getSizeInBits();
1605 int NumParts = TotalSize / NarrowSize;
1608 for (
int I = 0;
I != NumParts; ++
I) {
1609 unsigned Offset =
I * NarrowSize;
1616 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1618 if (LeftoverBits != 0) {
1622 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1626 insertParts(
MI.getOperand(0).getReg(),
1627 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1629 MI.eraseFromParent();
1632 case TargetOpcode::G_SEXT:
1633 case TargetOpcode::G_ZEXT:
1634 case TargetOpcode::G_ANYEXT:
1636 case TargetOpcode::G_TRUNC: {
1640 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1642 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1646 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1647 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1648 MI.eraseFromParent();
1651 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1652 case TargetOpcode::G_FREEZE: {
1656 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1661 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1663 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1665 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1669 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1670 MI.eraseFromParent();
1673 case TargetOpcode::G_ADD:
1674 case TargetOpcode::G_SUB:
1675 case TargetOpcode::G_SADDO:
1676 case TargetOpcode::G_SSUBO:
1677 case TargetOpcode::G_SADDE:
1678 case TargetOpcode::G_SSUBE:
1679 case TargetOpcode::G_UADDO:
1680 case TargetOpcode::G_USUBO:
1681 case TargetOpcode::G_UADDE:
1682 case TargetOpcode::G_USUBE:
1684 case TargetOpcode::G_MUL:
1685 case TargetOpcode::G_UMULH:
1687 case TargetOpcode::G_EXTRACT:
1689 case TargetOpcode::G_INSERT:
1691 case TargetOpcode::G_LOAD: {
1693 Register DstReg = LoadMI.getDstReg();
1694 LLT DstTy = MRI.getType(DstReg);
1698 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1699 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1700 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1702 LoadMI.eraseFromParent();
1708 case TargetOpcode::G_ZEXTLOAD:
1709 case TargetOpcode::G_SEXTLOAD:
1710 case TargetOpcode::G_FPEXTLOAD: {
1712 Register DstReg = LoadMI.getDstReg();
1713 Register PtrReg = LoadMI.getPointerReg();
1715 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1716 auto &MMO = LoadMI.getMMO();
1719 if (MemSize == NarrowSize) {
1721 }
else if (MemSize < NarrowSize) {
1722 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1723 }
else if (MemSize > NarrowSize) {
1735 LoadMI.eraseFromParent();
1738 case TargetOpcode::G_STORE: {
1741 Register SrcReg = StoreMI.getValueReg();
1742 LLT SrcTy = MRI.getType(SrcReg);
1743 if (SrcTy.isVector())
1746 int NumParts = SizeOp0 / NarrowSize;
1748 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1749 if (SrcTy.isVector() && LeftoverBits != 0)
1752 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1753 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1755 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1756 StoreMI.eraseFromParent();
1762 case TargetOpcode::G_FPTRUNCSTORE: {
1764 Register SrcReg = StoreMI.getValueReg();
1765 Register PtrReg = StoreMI.getPointerReg();
1767 auto &MMO = StoreMI.getMMO();
1769 if (MemSize > NarrowSize) {
1773 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1774 if (MemSize == NarrowSize) {
1776 }
else if (MemSize < NarrowSize) {
1777 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1781 StoreMI.eraseFromParent();
1784 case TargetOpcode::G_SELECT:
1786 case TargetOpcode::G_AND:
1787 case TargetOpcode::G_OR:
1788 case TargetOpcode::G_XOR: {
1800 case TargetOpcode::G_SHL:
1801 case TargetOpcode::G_LSHR:
1802 case TargetOpcode::G_ASHR:
1804 case TargetOpcode::G_CTLZ:
1805 case TargetOpcode::G_CTLZ_ZERO_POISON:
1806 case TargetOpcode::G_CTTZ:
1807 case TargetOpcode::G_CTTZ_ZERO_POISON:
1808 case TargetOpcode::G_CTLS:
1809 case TargetOpcode::G_CTPOP:
1811 switch (
MI.getOpcode()) {
1812 case TargetOpcode::G_CTLZ:
1813 case TargetOpcode::G_CTLZ_ZERO_POISON:
1815 case TargetOpcode::G_CTTZ:
1816 case TargetOpcode::G_CTTZ_ZERO_POISON:
1818 case TargetOpcode::G_CTPOP:
1820 case TargetOpcode::G_CTLS:
1830 case TargetOpcode::G_INTTOPTR:
1838 case TargetOpcode::G_PTRTOINT:
1846 case TargetOpcode::G_PHI: {
1849 if (SizeOp0 % NarrowSize != 0)
1852 unsigned NumParts = SizeOp0 / NarrowSize;
1856 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1864 for (
unsigned i = 0; i < NumParts; ++i) {
1865 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1867 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1868 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1869 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1872 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1874 MI.eraseFromParent();
1877 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1878 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1882 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1888 case TargetOpcode::G_ICMP: {
1890 LLT SrcTy = MRI.getType(LHS);
1896 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1902 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1903 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1909 LLT ResTy = MRI.getType(Dst);
1914 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1916 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1917 auto LHS = std::get<0>(LHSAndRHS);
1918 auto RHS = std::get<1>(LHSAndRHS);
1919 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1926 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1927 auto LHS = std::get<0>(LHSAndRHS);
1928 auto RHS = std::get<1>(LHSAndRHS);
1929 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1930 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1931 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1932 TargetOpcode::G_ZEXT);
1939 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1940 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1941 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1946 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1950 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1955 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1959 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1962 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1965 LHSPartRegs[
I], RHSPartRegs[
I]);
1966 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1972 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1981 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1985 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1986 RHSLeftoverRegs[
I]);
1988 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1989 RHSLeftoverRegs[
I]);
1992 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1993 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1999 MI.eraseFromParent();
2002 case TargetOpcode::G_FCMP:
2011 case TargetOpcode::G_SEXT_INREG: {
2015 int64_t SizeInBits =
MI.getOperand(2).getImm();
2024 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2025 MO1.
setReg(TruncMIB.getReg(0));
2028 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2040 if (SizeOp0 % NarrowSize != 0)
2042 int NumParts = SizeOp0 / NarrowSize;
2050 for (
int i = 0; i < NumParts; ++i) {
2051 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2066 for (
int i = 0; i < NumParts; ++i) {
2069 PartialExtensionReg = DstRegs.
back();
2071 assert(PartialExtensionReg &&
2072 "Expected to visit partial extension before full");
2073 if (FullExtensionReg) {
2078 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2080 FullExtensionReg = DstRegs.
back();
2085 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2088 PartialExtensionReg = DstRegs.
back();
2094 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2095 MI.eraseFromParent();
2098 case TargetOpcode::G_BSWAP:
2099 case TargetOpcode::G_BITREVERSE: {
2100 if (SizeOp0 % NarrowSize != 0)
2105 unsigned NumParts = SizeOp0 / NarrowSize;
2106 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2109 for (
unsigned i = 0; i < NumParts; ++i) {
2110 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2111 {SrcRegs[NumParts - 1 - i]});
2115 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2118 MI.eraseFromParent();
2121 case TargetOpcode::G_PTR_ADD:
2122 case TargetOpcode::G_PTRMASK: {
2130 case TargetOpcode::G_FPTOUI:
2131 case TargetOpcode::G_FPTOSI:
2132 case TargetOpcode::G_FPTOUI_SAT:
2133 case TargetOpcode::G_FPTOSI_SAT:
2135 case TargetOpcode::G_FPEXT:
2142 case TargetOpcode::G_FLDEXP:
2143 case TargetOpcode::G_STRICT_FLDEXP:
2145 case TargetOpcode::G_VSCALE: {
2147 LLT Ty = MRI.getType(Dst);
2151 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2152 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2153 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2156 MI.eraseFromParent();
2163 LLT Ty = MRI.getType(Val);
2164 if (Ty.isScalar() && !Ty.isFloat())
2171 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2173 if (Ty.isPointer()) {
2174 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2176 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2182 if (Ty.isPointerVector())
2183 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2184 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2188 unsigned OpIdx,
unsigned ExtOpcode) {
2190 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2191 MO.
setReg(ExtB.getReg(0));
2197 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2199 MO.
setReg(ExtB.getReg(0));
2205 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2206 MO.
setReg(ExtB.getReg(0));
2210 unsigned OpIdx,
unsigned TruncOpcode) {
2212 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2214 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2221 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2223 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2228 unsigned OpIdx,
unsigned ExtOpcode) {
2230 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2232 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2241 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2243 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2249 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2259 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2266LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2271 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2272 if (DstTy.isVector())
2275 LLT SrcTy =
MRI.getType(Src1Reg);
2276 const int DstSize = DstTy.getSizeInBits();
2277 const int SrcSize = SrcTy.getSizeInBits();
2279 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2281 unsigned NumOps =
MI.getNumOperands();
2282 unsigned NumSrc =
MI.getNumOperands() - 1;
2283 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2285 if (WideSize >= DstSize) {
2289 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2290 const unsigned Offset = (
I - 1) * PartSize;
2298 MRI.createGenericVirtualRegister(WideTy);
2303 ResultReg = NextResult;
2306 if (WideSize > DstSize)
2308 else if (DstTy.isPointer())
2310 else if (DstTy != WideTy)
2313 MI.eraseFromParent();
2338 const int GCD = std::gcd(SrcSize, WideSize);
2348 if (GCD == SrcSize) {
2351 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2352 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2358 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2360 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2364 const int PartsPerGCD = WideSize / GCD;
2368 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2370 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2377 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2379 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2380 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2383 MI.eraseFromParent();
2388LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2393 int NumDst =
MI.getNumOperands() - 1;
2394 Register SrcReg =
MI.getOperand(NumDst).getReg();
2395 LLT SrcTy = MRI.getType(SrcReg);
2399 Register Dst0Reg =
MI.getOperand(0).getReg();
2400 LLT DstTy = MRI.getType(Dst0Reg);
2409 dbgs() <<
"Not casting non-integral address space integer\n");
2414 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2422 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2431 SrcTy = MRI.getType(SrcReg);
2435 for (
int I = 1;
I != NumDst; ++
I) {
2436 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2437 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2441 MI.eraseFromParent();
2452 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2456 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2459 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2477 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2482 if (PartsPerRemerge == 1) {
2485 for (
int I = 0;
I != NumUnmerge; ++
I) {
2486 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2488 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2489 int Idx =
I * PartsPerUnmerge + J;
2491 MIB.addDef(
MI.getOperand(Idx).getReg());
2494 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2498 MIB.addUse(Unmerge.getReg(
I));
2501 SmallVector<Register, 16> Parts;
2502 for (
int J = 0; J != NumUnmerge; ++J)
2503 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2506 for (
int I = 0;
I != NumDst; ++
I) {
2507 for (
int J = 0; J < PartsPerRemerge; ++J) {
2508 const int Idx =
I * PartsPerRemerge + J;
2512 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2513 RemergeParts.
clear();
2517 MI.eraseFromParent();
2522LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2524 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2525 unsigned Offset =
MI.getOperand(2).getImm();
2528 if (SrcTy.
isVector() || DstTy.isVector())
2540 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2544 if (DstTy.isPointer())
2551 MI.eraseFromParent();
2556 LLT ShiftTy = SrcTy;
2565 MI.eraseFromParent();
2596LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2598 if (TypeIdx != 0 || WideTy.
isVector())
2608LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2612 std::optional<Register> CarryIn;
2613 switch (
MI.getOpcode()) {
2616 case TargetOpcode::G_SADDO:
2617 Opcode = TargetOpcode::G_ADD;
2618 ExtOpcode = TargetOpcode::G_SEXT;
2620 case TargetOpcode::G_SSUBO:
2621 Opcode = TargetOpcode::G_SUB;
2622 ExtOpcode = TargetOpcode::G_SEXT;
2624 case TargetOpcode::G_UADDO:
2625 Opcode = TargetOpcode::G_ADD;
2626 ExtOpcode = TargetOpcode::G_ZEXT;
2628 case TargetOpcode::G_USUBO:
2629 Opcode = TargetOpcode::G_SUB;
2630 ExtOpcode = TargetOpcode::G_ZEXT;
2632 case TargetOpcode::G_SADDE:
2633 Opcode = TargetOpcode::G_UADDE;
2634 ExtOpcode = TargetOpcode::G_SEXT;
2635 CarryIn =
MI.getOperand(4).getReg();
2637 case TargetOpcode::G_SSUBE:
2638 Opcode = TargetOpcode::G_USUBE;
2639 ExtOpcode = TargetOpcode::G_SEXT;
2640 CarryIn =
MI.getOperand(4).getReg();
2642 case TargetOpcode::G_UADDE:
2643 Opcode = TargetOpcode::G_UADDE;
2644 ExtOpcode = TargetOpcode::G_ZEXT;
2645 CarryIn =
MI.getOperand(4).getReg();
2647 case TargetOpcode::G_USUBE:
2648 Opcode = TargetOpcode::G_USUBE;
2649 ExtOpcode = TargetOpcode::G_ZEXT;
2650 CarryIn =
MI.getOperand(4).getReg();
2666 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2667 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2671 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2673 .buildInstr(Opcode, {WideTy, CarryOutTy},
2674 {LHSExt, RHSExt, *CarryIn})
2677 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2679 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2680 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2681 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2686 MI.eraseFromParent();
2691LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2693 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2694 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2695 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2696 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2697 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2710 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2717 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2721 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2722 {ShiftL, ShiftR},
MI.getFlags());
2727 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2730 MI.eraseFromParent();
2735LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2744 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2746 LLT SrcTy = MRI.getType(
LHS);
2747 LLT OverflowTy = MRI.getType(OriginalOverflow);
2754 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2755 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2756 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2763 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2765 MachineInstrBuilder Mulo;
2766 if (WideMulCanOverflow)
2767 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2768 {LeftOperand, RightOperand});
2770 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2775 MachineInstrBuilder ExtResult;
2782 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2786 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2789 if (WideMulCanOverflow) {
2797 MI.eraseFromParent();
2803 unsigned Opcode =
MI.getOpcode();
2807 case TargetOpcode::G_ATOMICRMW_XCHG:
2808 case TargetOpcode::G_ATOMICRMW_ADD:
2809 case TargetOpcode::G_ATOMICRMW_SUB:
2810 case TargetOpcode::G_ATOMICRMW_AND:
2811 case TargetOpcode::G_ATOMICRMW_OR:
2812 case TargetOpcode::G_ATOMICRMW_XOR:
2813 case TargetOpcode::G_ATOMICRMW_MIN:
2814 case TargetOpcode::G_ATOMICRMW_MAX:
2815 case TargetOpcode::G_ATOMICRMW_UMIN:
2816 case TargetOpcode::G_ATOMICRMW_UMAX:
2817 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2823 case TargetOpcode::G_ATOMIC_CMPXCHG:
2824 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2831 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2841 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2846 case TargetOpcode::G_EXTRACT:
2847 return widenScalarExtract(
MI, TypeIdx, WideTy);
2848 case TargetOpcode::G_INSERT:
2849 return widenScalarInsert(
MI, TypeIdx, WideTy);
2850 case TargetOpcode::G_MERGE_VALUES:
2851 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2852 case TargetOpcode::G_UNMERGE_VALUES:
2853 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2854 case TargetOpcode::G_SADDO:
2855 case TargetOpcode::G_SSUBO:
2856 case TargetOpcode::G_UADDO:
2857 case TargetOpcode::G_USUBO:
2858 case TargetOpcode::G_SADDE:
2859 case TargetOpcode::G_SSUBE:
2860 case TargetOpcode::G_UADDE:
2861 case TargetOpcode::G_USUBE:
2862 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2863 case TargetOpcode::G_UMULO:
2864 case TargetOpcode::G_SMULO:
2865 return widenScalarMulo(
MI, TypeIdx, WideTy);
2866 case TargetOpcode::G_SADDSAT:
2867 case TargetOpcode::G_SSUBSAT:
2868 case TargetOpcode::G_SSHLSAT:
2869 case TargetOpcode::G_UADDSAT:
2870 case TargetOpcode::G_USUBSAT:
2871 case TargetOpcode::G_USHLSAT:
2872 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2873 case TargetOpcode::G_CTTZ:
2874 case TargetOpcode::G_CTTZ_ZERO_POISON:
2875 case TargetOpcode::G_CTLZ:
2876 case TargetOpcode::G_CTLZ_ZERO_POISON:
2877 case TargetOpcode::G_CTLS:
2878 case TargetOpcode::G_CTPOP: {
2891 case TargetOpcode::G_CTTZ:
2892 case TargetOpcode::G_CTTZ_ZERO_POISON:
2893 case TargetOpcode::G_CTLZ_ZERO_POISON:
2894 ExtOpc = TargetOpcode::G_ANYEXT;
2896 case TargetOpcode::G_CTLS:
2897 ExtOpc = TargetOpcode::G_SEXT;
2900 ExtOpc = TargetOpcode::G_ZEXT;
2903 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2904 LLT CurTy = MRI.getType(SrcReg);
2905 unsigned NewOpc = Opcode;
2906 if (NewOpc == TargetOpcode::G_CTTZ) {
2913 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2915 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2921 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2931 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2933 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2938 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2939 Opcode == TargetOpcode::G_CTLZ
2944 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2945 MI.eraseFromParent();
2948 case TargetOpcode::G_BSWAP: {
2952 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2953 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2954 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2957 MI.getOperand(0).setReg(DstExt);
2961 LLT Ty = MRI.getType(DstReg);
2963 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2964 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2970 case TargetOpcode::G_BITREVERSE: {
2974 LLT Ty = MRI.getType(DstReg);
2977 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2979 MI.getOperand(0).setReg(DstExt);
2982 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2983 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2988 case TargetOpcode::G_FREEZE:
2989 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2996 case TargetOpcode::G_ABS:
3003 case TargetOpcode::G_ADD:
3004 case TargetOpcode::G_AND:
3005 case TargetOpcode::G_MUL:
3006 case TargetOpcode::G_OR:
3007 case TargetOpcode::G_XOR:
3008 case TargetOpcode::G_SUB:
3009 case TargetOpcode::G_SHUFFLE_VECTOR:
3025 case TargetOpcode::G_SBFX:
3026 case TargetOpcode::G_UBFX:
3040 case TargetOpcode::G_SHL:
3060 case TargetOpcode::G_ROTR:
3061 case TargetOpcode::G_ROTL:
3070 case TargetOpcode::G_SDIV:
3071 case TargetOpcode::G_SREM:
3072 case TargetOpcode::G_SMIN:
3073 case TargetOpcode::G_SMAX:
3074 case TargetOpcode::G_ABDS:
3082 case TargetOpcode::G_SDIVREM:
3092 case TargetOpcode::G_ASHR:
3093 case TargetOpcode::G_LSHR:
3097 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3098 : TargetOpcode::G_ZEXT;
3111 case TargetOpcode::G_UDIV:
3112 case TargetOpcode::G_UREM:
3113 case TargetOpcode::G_ABDU:
3120 case TargetOpcode::G_UDIVREM:
3129 case TargetOpcode::G_UMIN:
3130 case TargetOpcode::G_UMAX: {
3131 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3133 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3137 ? TargetOpcode::G_SEXT
3138 : TargetOpcode::G_ZEXT;
3148 case TargetOpcode::G_SELECT:
3158 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3165 case TargetOpcode::G_FPEXT:
3173 case TargetOpcode::G_FPTOSI:
3174 case TargetOpcode::G_FPTOUI:
3175 case TargetOpcode::G_INTRINSIC_LRINT:
3176 case TargetOpcode::G_INTRINSIC_LLRINT:
3177 case TargetOpcode::G_IS_FPCLASS:
3187 case TargetOpcode::G_SITOFP:
3197 case TargetOpcode::G_UITOFP:
3207 case TargetOpcode::G_FPTOSI_SAT:
3208 case TargetOpcode::G_FPTOUI_SAT:
3213 LLT Ty = MRI.getType(OldDst);
3214 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3216 MI.getOperand(0).setReg(ExtReg);
3217 uint64_t ShortBits = Ty.getScalarSizeInBits();
3220 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3231 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3232 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3240 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3248 case TargetOpcode::G_LOAD:
3249 case TargetOpcode::G_SEXTLOAD:
3250 case TargetOpcode::G_ZEXTLOAD:
3251 case TargetOpcode::G_FPEXTLOAD:
3257 case TargetOpcode::G_STORE: {
3261 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3262 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3263 if (!Ty.isScalar()) {
3271 MI.setMemRefs(MF, {NewMMO});
3278 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3279 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3285 case TargetOpcode::G_FPTRUNCSTORE:
3292 case TargetOpcode::G_CONSTANT: {
3295 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3296 MRI.getType(
MI.getOperand(0).getReg()));
3297 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3298 ExtOpc == TargetOpcode::G_ANYEXT) &&
3301 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3305 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3311 case TargetOpcode::G_FCONSTANT: {
3317 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3319 MI.eraseFromParent();
3322 case TargetOpcode::G_IMPLICIT_DEF: {
3328 case TargetOpcode::G_BRCOND:
3334 case TargetOpcode::G_FCMP:
3345 case TargetOpcode::G_ICMP:
3350 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3354 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3355 unsigned ExtOpcode =
3359 ? TargetOpcode::G_SEXT
3360 : TargetOpcode::G_ZEXT;
3367 case TargetOpcode::G_PTR_ADD:
3368 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3374 case TargetOpcode::G_PHI: {
3375 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3378 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3390 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3393 LLT VecTy = MRI.getType(VecReg);
3397 TargetOpcode::G_ANYEXT);
3411 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3427 LLT VecTy = MRI.getType(VecReg);
3446 case TargetOpcode::G_FADD:
3447 case TargetOpcode::G_FMUL:
3448 case TargetOpcode::G_FSUB:
3449 case TargetOpcode::G_FMA:
3450 case TargetOpcode::G_FMAD:
3451 case TargetOpcode::G_FNEG:
3452 case TargetOpcode::G_FABS:
3453 case TargetOpcode::G_FCANONICALIZE:
3454 case TargetOpcode::G_FMINNUM:
3455 case TargetOpcode::G_FMAXNUM:
3456 case TargetOpcode::G_FMINNUM_IEEE:
3457 case TargetOpcode::G_FMAXNUM_IEEE:
3458 case TargetOpcode::G_FMINIMUM:
3459 case TargetOpcode::G_FMAXIMUM:
3460 case TargetOpcode::G_FMINIMUMNUM:
3461 case TargetOpcode::G_FMAXIMUMNUM:
3462 case TargetOpcode::G_FDIV:
3463 case TargetOpcode::G_FREM:
3464 case TargetOpcode::G_FCEIL:
3465 case TargetOpcode::G_FFLOOR:
3466 case TargetOpcode::G_FCOS:
3467 case TargetOpcode::G_FSIN:
3468 case TargetOpcode::G_FTAN:
3469 case TargetOpcode::G_FACOS:
3470 case TargetOpcode::G_FASIN:
3471 case TargetOpcode::G_FATAN:
3472 case TargetOpcode::G_FATAN2:
3473 case TargetOpcode::G_FCOSH:
3474 case TargetOpcode::G_FSINH:
3475 case TargetOpcode::G_FTANH:
3476 case TargetOpcode::G_FLOG10:
3477 case TargetOpcode::G_FLOG:
3478 case TargetOpcode::G_FLOG2:
3479 case TargetOpcode::G_FRINT:
3480 case TargetOpcode::G_FNEARBYINT:
3481 case TargetOpcode::G_FSQRT:
3482 case TargetOpcode::G_FEXP:
3483 case TargetOpcode::G_FEXP2:
3484 case TargetOpcode::G_FEXP10:
3485 case TargetOpcode::G_FPOW:
3486 case TargetOpcode::G_INTRINSIC_TRUNC:
3487 case TargetOpcode::G_INTRINSIC_ROUND:
3488 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3492 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3498 case TargetOpcode::G_FMODF: {
3508 case TargetOpcode::G_FPOWI:
3509 case TargetOpcode::G_FLDEXP:
3510 case TargetOpcode::G_STRICT_FLDEXP: {
3512 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3533 case TargetOpcode::G_FFREXP: {
3546 case TargetOpcode::G_LROUND:
3547 case TargetOpcode::G_LLROUND:
3558 case TargetOpcode::G_INTTOPTR:
3566 case TargetOpcode::G_PTRTOINT:
3574 case TargetOpcode::G_BUILD_VECTOR: {
3578 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3584 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3592 case TargetOpcode::G_SEXT_INREG:
3601 case TargetOpcode::G_PTRMASK: {
3609 case TargetOpcode::G_VECREDUCE_ADD: {
3618 case TargetOpcode::G_VECREDUCE_FADD:
3619 case TargetOpcode::G_VECREDUCE_FMUL:
3620 case TargetOpcode::G_VECREDUCE_FMIN:
3621 case TargetOpcode::G_VECREDUCE_FMAX:
3622 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3623 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3628 LLT VecTy = MRI.getType(VecReg);
3635 case TargetOpcode::G_VSCALE: {
3642 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3647 case TargetOpcode::G_SPLAT_VECTOR: {
3656 case TargetOpcode::G_INSERT_SUBVECTOR: {
3664 LLT SubVecTy = MRI.getType(SubVec);
3668 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3669 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3670 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3674 auto SplatZero =
MIRBuilder.buildSplatVector(
3679 MI.eraseFromParent();
3683 case TargetOpcode::G_BITCAST:
3695 if (MRI.getType(Dst) == MRI.getType(Src)) {
3696 Observer.changingAllUsesOfReg(MRI, Dst);
3697 MRI.replaceRegWith(Dst, Src);
3698 Observer.finishedChangingAllUsesOfReg();
3699 MI.eraseFromParent();
3708 auto Unmerge =
B.buildUnmerge(Ty, Src);
3709 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3718 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3720 LLT DstLLT =
MRI.getType(DstReg);
3732 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3741 MI.eraseFromParent();
3749 const ConstantFP *ConstantVal =
MI.getOperand(1).getFPImm();
3752 bool ForCodeSize =
MIRBuilder.getMF().getFunction().hasOptSize();
3753 if (TLI.getFPImmAction(
Imm, MRI.getType(Dst), ForCodeSize) ==
3759 MI.eraseFromParent();
3765 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3766 if (SrcTy.isVector()) {
3770 if (DstTy.isVector()) {
3785 unsigned PieceSize =
3801 MI.eraseFromParent();
3806 LLT::vector(SrcEC * (SrcEltSize / PieceSize), PieceTy);
3808 MIRBuilder.buildBitcast(PiecesVecTy, Src).getReg(0);
3810 MI.eraseFromParent();
3817 LLT DstCastTy = DstEltTy;
3818 LLT SrcPartTy = SrcEltTy;
3822 if (NumSrcElt < NumDstElt) {
3833 SrcPartTy = SrcEltTy;
3834 }
else if (NumSrcElt > NumDstElt) {
3846 DstCastTy = DstEltTy;
3851 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3855 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3856 MI.eraseFromParent();
3860 if (DstTy.isVector()) {
3863 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3864 MI.eraseFromParent();
3880 unsigned NewEltSize,
3881 unsigned OldEltSize) {
3882 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3883 LLT IdxTy =
B.getMRI()->getType(Idx);
3886 auto OffsetMask =
B.buildConstant(
3888 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3889 return B.buildShl(IdxTy, OffsetIdx,
3890 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3905 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3909 unsigned OldNumElts = SrcVecTy.getNumElements();
3916 if (NewNumElts > OldNumElts) {
3927 if (NewNumElts % OldNumElts != 0)
3931 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3935 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3938 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3940 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3941 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3942 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3943 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3944 NewOps[
I] = Elt.getReg(0);
3947 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3949 MI.eraseFromParent();
3953 if (NewNumElts < OldNumElts) {
3954 if (NewEltSize % OldEltSize != 0)
3976 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3977 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3980 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3984 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3985 ScaledIdx).getReg(0);
3993 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3995 MI.eraseFromParent();
4009 LLT TargetTy =
B.getMRI()->getType(TargetReg);
4010 LLT InsertTy =
B.getMRI()->getType(InsertReg);
4011 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
4012 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
4015 auto EltMask =
B.buildConstant(
4019 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
4020 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
4023 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
4027 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
4041 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
4042 MI.getFirst4RegLLTs();
4054 if (NewNumElts < OldNumElts) {
4055 if (NewEltSize % OldEltSize != 0)
4064 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4065 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4068 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4072 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4073 ScaledIdx).getReg(0);
4083 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4084 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4088 MI.eraseFromParent();
4118 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4122 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4123 return UnableToLegalize;
4128 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4130 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4139 MI.eraseFromParent();
4157 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4158 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4168 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4169 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4171 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4172 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4174 MI.eraseFromParent();
4200 uint64_t Idx = ES->getIndexImm();
4204 LLT DstTy = MRI.getType(Dst);
4205 LLT SrcTy = MRI.getType(Src);
4211 if (DstTy == CastTy)
4219 if (CastEltSize < DstEltSize)
4222 auto AdjustAmt = CastEltSize / DstEltSize;
4223 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4224 SrcTyMinElts % AdjustAmt != 0)
4229 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4230 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4233 ES->eraseFromParent();
4264 uint64_t Idx = ES->getIndexImm();
4268 LLT DstTy = MRI.getType(Dst);
4269 LLT BigVecTy = MRI.getType(BigVec);
4270 LLT SubVecTy = MRI.getType(SubVec);
4272 if (DstTy == CastTy)
4287 if (CastEltSize < DstEltSize)
4290 auto AdjustAmt = CastEltSize / DstEltSize;
4291 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4292 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4298 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4299 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4301 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4304 ES->eraseFromParent();
4312 LLT DstTy = MRI.getType(DstReg);
4322 if (MemSizeInBits != MemStoreSizeInBits) {
4339 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4343 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4344 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4346 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4349 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4351 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4354 if (DstTy != LoadTy)
4362 if (
MIRBuilder.getDataLayout().isBigEndian())
4380 uint64_t LargeSplitSize, SmallSplitSize;
4385 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4392 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4395 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4406 if (Alignment.value() * 8 > MemSizeInBits &&
4411 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4428 LLT PtrTy = MRI.getType(PtrReg);
4434 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4437 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4438 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4439 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4441 SmallPtr, *SmallMMO);
4443 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4444 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4446 if (AnyExtTy == DstTy)
4447 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4449 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4451 if (IntDstTy == DstTy) {
4458 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4464 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4481 LLT SrcTy = MRI.getType(SrcReg);
4489 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4495 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4497 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4501 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4505 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4520 uint64_t LargeSplitSize, SmallSplitSize;
4527 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4530 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4539 if (SrcTy.isPointer()) {
4544 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4547 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4548 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4551 LLT PtrTy = MRI.getType(PtrReg);
4553 LargeSplitSize / 8);
4554 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4560 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4561 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4570 LLT SrcTy = MRI.getType(SrcReg);
4576 assert(SrcTy.isVector() &&
"Expect a vector store type");
4583 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4587 auto Elt =
MIRBuilder.buildExtractVectorElement(
4588 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4589 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4590 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4596 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4597 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4601 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4612 switch (
MI.getOpcode()) {
4613 case TargetOpcode::G_LOAD: {
4631 case TargetOpcode::G_STORE: {
4647 case TargetOpcode::G_SELECT: {
4651 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4653 dbgs() <<
"bitcast action not implemented for vector select\n");
4664 case TargetOpcode::G_AND:
4665 case TargetOpcode::G_OR:
4666 case TargetOpcode::G_XOR: {
4674 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4676 case TargetOpcode::G_INSERT_VECTOR_ELT:
4678 case TargetOpcode::G_CONCAT_VECTORS:
4680 case TargetOpcode::G_SHUFFLE_VECTOR:
4682 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4684 case TargetOpcode::G_INSERT_SUBVECTOR:
4692void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4701 switch(
MI.getOpcode()) {
4704 case TargetOpcode::G_FCONSTANT:
4706 case TargetOpcode::G_BITCAST:
4708 case TargetOpcode::G_SREM:
4709 case TargetOpcode::G_UREM: {
4710 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4712 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4713 {MI.getOperand(1), MI.getOperand(2)});
4715 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4717 MI.eraseFromParent();
4720 case TargetOpcode::G_SADDO:
4721 case TargetOpcode::G_SSUBO:
4723 case TargetOpcode::G_SADDE:
4725 case TargetOpcode::G_SSUBE:
4727 case TargetOpcode::G_UMULH:
4728 case TargetOpcode::G_SMULH:
4730 case TargetOpcode::G_SMULO:
4731 case TargetOpcode::G_UMULO: {
4734 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4735 LLT Ty = MRI.getType(Res);
4737 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4738 ? TargetOpcode::G_SMULH
4739 : TargetOpcode::G_UMULH;
4743 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4744 MI.removeOperand(1);
4747 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4755 if (Opcode == TargetOpcode::G_SMULH) {
4756 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4757 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4764 case TargetOpcode::G_FNEG: {
4765 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4768 Register CastedSubByReg = SubByReg;
4770 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4771 !SubByRegTy.getScalarType().isInteger()) {
4772 auto BitcastDst = SubByRegTy.changeElementType(
4774 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4780 if (ResTy != TyInt) {
4782 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4785 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4787 MI.eraseFromParent();
4790 case TargetOpcode::G_FSUB:
4791 case TargetOpcode::G_STRICT_FSUB: {
4792 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4793 LLT Ty = MRI.getType(Res);
4798 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4799 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4803 MI.eraseFromParent();
4806 case TargetOpcode::G_FMAD:
4808 case TargetOpcode::G_FFLOOR:
4810 case TargetOpcode::G_LROUND:
4811 case TargetOpcode::G_LLROUND: {
4814 LLT SrcTy = MRI.getType(SrcReg);
4815 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4818 MI.eraseFromParent();
4821 case TargetOpcode::G_INTRINSIC_ROUND:
4823 case TargetOpcode::G_FRINT: {
4826 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4829 case TargetOpcode::G_INTRINSIC_LRINT:
4830 case TargetOpcode::G_INTRINSIC_LLRINT: {
4833 LLT SrcTy = MRI.getType(SrcReg);
4835 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4837 MI.eraseFromParent();
4840 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4841 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4842 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4843 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4844 **
MI.memoperands_begin());
4846 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4847 MI.eraseFromParent();
4850 case TargetOpcode::G_LOAD:
4851 case TargetOpcode::G_SEXTLOAD:
4852 case TargetOpcode::G_ZEXTLOAD:
4854 case TargetOpcode::G_STORE:
4856 case TargetOpcode::G_CTLZ_ZERO_POISON:
4857 case TargetOpcode::G_CTTZ_ZERO_POISON:
4858 case TargetOpcode::G_CTLZ:
4859 case TargetOpcode::G_CTTZ:
4860 case TargetOpcode::G_CTPOP:
4861 case TargetOpcode::G_CTLS:
4864 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4866 Register NewRes = MRI.cloneVirtualRegister(Res);
4873 MI.eraseFromParent();
4877 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4878 const LLT CondTy = MRI.getType(CarryOut);
4879 const LLT Ty = MRI.getType(Res);
4881 Register NewRes = MRI.cloneVirtualRegister(Res);
4884 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4890 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4891 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4898 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4903 MI.eraseFromParent();
4907 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4912 MI.eraseFromParent();
4916 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4917 const LLT CondTy = MRI.getType(BorrowOut);
4918 const LLT Ty = MRI.getType(Res);
4921 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4927 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4928 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4935 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4936 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4938 MI.eraseFromParent();
4978 case G_MERGE_VALUES:
4980 case G_UNMERGE_VALUES:
4982 case TargetOpcode::G_SEXT_INREG: {
4983 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4984 int64_t SizeInBits =
MI.getOperand(2).getImm();
4986 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4987 LLT DstTy = MRI.getType(DstReg);
4988 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4991 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4992 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4993 MI.eraseFromParent();
4996 case G_EXTRACT_VECTOR_ELT:
4997 case G_INSERT_VECTOR_ELT:
4999 case G_SHUFFLE_VECTOR:
5001 case G_VECTOR_COMPRESS:
5003 case G_DYN_STACKALLOC:
5005 case G_INSERT_SUBVECTOR: {
5006 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
5007 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
5012 Register Subvector =
MI.getOperand(2).getReg();
5013 auto InsertionPointImm =
MI.getOperand(3).getImm();
5016 LLT DstTy = MRI.getType(Subvector);
5020 bool InsertInLowHalf = InsertionPointImm == 0;
5021 auto Extract =
MIRBuilder.buildExtractSubvector(
5023 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
5025 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
5026 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
5028 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
5029 {LowHalf, HighHalf});
5030 MI.eraseFromParent();
5036 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
5037 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
5043 if (i >= InsertionPointImm &&
5045 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
5053 MI.eraseFromParent();
5057 case G_EXTRACT_SUBVECTOR: {
5060 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5062 LLT SrcTy = MRI.getType(SrcReg);
5063 LLT DstTy = MRI.getType(DstReg);
5065 if (SrcTy.isScalable())
5076 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5077 ExtractionPointImm + i)
5081 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5082 MI.eraseFromParent();
5087 case G_STACKRESTORE:
5097 case G_READ_REGISTER:
5098 case G_WRITE_REGISTER:
5105 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5106 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5112 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5117 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5124 case G_TRUNC_SSAT_S:
5125 case G_TRUNC_USAT_U:
5126 case G_TRUNC_SSAT_U:
5132 bool IsSigned =
MI.getOpcode() == G_ABDS;
5133 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5134 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5135 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5158 case G_MEMCPY_INLINE:
5159 case G_MEMSET_INLINE:
5171 case G_ATOMICRMW_SUB: {
5172 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5173 const LLT ValTy = MRI.getType(Val);
5177 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5178 MI.eraseFromParent();
5206 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5210 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5216 Align StackTypeAlign =
5223 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5224 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5229 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5241 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5244 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5255 "Converting bits to bytes lost precision");
5261 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5262 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5264 if (IdxTy != MRI.getType(Index))
5265 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5270 LLT PtrTy = MRI.getType(VecPtr);
5271 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5279 std::initializer_list<unsigned> NonVecOpIndices) {
5280 if (
MI.getNumMemOperands() != 0)
5283 LLT VecTy =
MRI.getType(
MI.getReg(0));
5288 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5297 if (!Ty.isVector()) {
5303 if (Ty.getNumElements() != NumElts)
5318 assert(Ty.isVector() &&
"Expected vector type");
5320 int NumParts, NumLeftover;
5321 std::tie(NumParts, NumLeftover) =
5324 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5325 for (
int i = 0; i < NumParts; ++i) {
5330 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5339 for (
unsigned i = 0; i <
N; ++i) {
5341 Ops.push_back(
Op.getReg());
5342 else if (
Op.isImm())
5343 Ops.push_back(
Op.getImm());
5344 else if (
Op.isPredicate())
5366 std::initializer_list<unsigned> NonVecOpIndices) {
5368 "Non-compatible opcode or not specified non-vector operands");
5369 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5371 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5372 unsigned NumDefs =
MI.getNumDefs();
5380 for (
unsigned i = 0; i < NumDefs; ++i) {
5381 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5389 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5390 ++UseIdx, ++UseNo) {
5393 MI.getOperand(UseIdx));
5402 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5406 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5408 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5409 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5412 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5413 Uses.push_back(InputOpsPieces[InputNo][i]);
5416 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5417 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5422 for (
unsigned i = 0; i < NumDefs; ++i)
5423 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5425 for (
unsigned i = 0; i < NumDefs; ++i)
5426 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5429 MI.eraseFromParent();
5436 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5438 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5439 unsigned NumDefs =
MI.getNumDefs();
5443 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5448 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5449 UseIdx += 2, ++UseNo) {
5457 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5459 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5460 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5462 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5465 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5466 Phi.addUse(InputOpsPieces[j][i]);
5467 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5477 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5479 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5482 MI.eraseFromParent();
5490 const int NumDst =
MI.getNumOperands() - 1;
5491 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5492 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5493 LLT SrcTy = MRI.getType(SrcReg);
5495 if (TypeIdx != 1 || NarrowTy == DstTy)
5502 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5505 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5519 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5520 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5521 const int PartsPerUnmerge = NumDst / NumUnmerge;
5523 for (
int I = 0;
I != NumUnmerge; ++
I) {
5524 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5526 for (
int J = 0; J != PartsPerUnmerge; ++J)
5527 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5528 MIB.addUse(Unmerge.getReg(
I));
5531 MI.eraseFromParent();
5538 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5542 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5544 if (NarrowTy == SrcTy)
5552 assert(SrcTy.isVector() &&
"Expected vector types");
5554 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5568 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5569 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5570 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5576 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5577 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5578 ++i,
Offset += NumNarrowTyElts) {
5581 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5584 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5585 MI.eraseFromParent();
5589 assert(TypeIdx == 0 &&
"Bad type index");
5590 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5605 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5606 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5608 for (
unsigned i = 0; i < NumParts; ++i) {
5610 for (
unsigned j = 0; j < NumElts; ++j)
5611 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5613 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5616 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5617 MI.eraseFromParent();
5625 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5627 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5629 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5631 InsertVal =
MI.getOperand(2).getReg();
5633 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5634 LLT VecTy = MRI.getType(SrcVec);
5640 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5644 MI.eraseFromParent();
5653 SplitPieces[IdxVal] = InsertVal;
5654 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5656 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5660 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5663 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5664 TargetOpcode::G_ANYEXT);
5668 LLT IdxTy = MRI.getType(Idx);
5669 int64_t PartIdx = IdxVal / NewNumElts;
5671 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5674 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5677 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5678 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5679 VecParts[PartIdx] = InsertPart.getReg(0);
5683 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5685 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5689 MI.eraseFromParent();
5709 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5721 LLT ValTy = MRI.getType(ValReg);
5730 int NumLeftover = -1;
5736 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5738 NumParts = NarrowRegs.
size();
5739 NumLeftover = NarrowLeftoverRegs.
size();
5746 LLT PtrTy = MRI.getType(AddrReg);
5756 auto MMO = LdStMI.
getMMO();
5758 unsigned NumParts,
unsigned Offset) ->
unsigned {
5761 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5763 unsigned ByteOffset =
Offset / 8;
5766 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5773 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5774 ValRegs.push_back(Dst);
5775 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5777 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5786 unsigned HandledOffset =
5787 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5791 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5794 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5795 LeftoverTy, NarrowLeftoverRegs);
5809 switch (
MI.getOpcode()) {
5810 case G_IMPLICIT_DEF:
5826 case G_FCANONICALIZE:
5843 case G_INTRINSIC_LRINT:
5844 case G_INTRINSIC_LLRINT:
5845 case G_INTRINSIC_ROUND:
5846 case G_INTRINSIC_ROUNDEVEN:
5849 case G_INTRINSIC_TRUNC:
5877 case G_FMINNUM_IEEE:
5878 case G_FMAXNUM_IEEE:
5900 case G_CTLZ_ZERO_POISON:
5902 case G_CTTZ_ZERO_POISON:
5919 case G_ADDRSPACE_CAST:
5932 case G_STRICT_FLDEXP:
5934 case G_TRUNC_SSAT_S:
5935 case G_TRUNC_SSAT_U:
5936 case G_TRUNC_USAT_U:
5944 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5949 case G_UNMERGE_VALUES:
5951 case G_BUILD_VECTOR:
5952 assert(TypeIdx == 0 &&
"not a vector type index");
5954 case G_CONCAT_VECTORS:
5958 case G_EXTRACT_SUBVECTOR: {
5960 LLT DstTy = MRI.getType(DstReg);
5962 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5972 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5973 uint64_t RequiredSubvectorIndex =
5977 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5980 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5983 MI.eraseFromParent();
5986 case G_EXTRACT_VECTOR_ELT:
5987 case G_INSERT_VECTOR_ELT:
5996 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5997 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5999 case G_SHUFFLE_VECTOR:
6005 case G_INTRINSIC_FPTRUNC_ROUND:
6015 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
6016 "Not a bitcast operation");
6021 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6023 unsigned NewElemCount =
6026 if (NewElemCount == 1) {
6029 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
6036 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
6045 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
6046 MI.eraseFromParent();
6052 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6056 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6057 MI.getFirst3RegLLTs();
6060 if (DstTy != Src1Ty)
6062 if (DstTy != Src2Ty)
6077 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6093 unsigned InputUsed[2] = {-1U, -1U};
6094 unsigned FirstMaskIdx =
High * NewElts;
6095 bool UseBuildVector =
false;
6096 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6098 int Idx = Mask[FirstMaskIdx + MaskOffset];
6103 if (
Input >= std::size(Inputs)) {
6110 Idx -=
Input * NewElts;
6114 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6115 if (InputUsed[OpNo] ==
Input) {
6118 }
else if (InputUsed[OpNo] == -1U) {
6120 InputUsed[OpNo] =
Input;
6125 if (OpNo >= std::size(InputUsed)) {
6128 UseBuildVector =
true;
6133 Ops.push_back(Idx + OpNo * NewElts);
6136 if (UseBuildVector) {
6141 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6143 int Idx = Mask[FirstMaskIdx + MaskOffset];
6148 if (
Input >= std::size(Inputs)) {
6155 Idx -=
Input * NewElts;
6159 .buildExtractVectorElement(
6160 EltTy, Inputs[
Input],
6166 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6167 }
else if (InputUsed[0] == -1U) {
6169 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6170 }
else if (NewElts == 1) {
6171 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6173 Register Op0 = Inputs[InputUsed[0]];
6177 : Inputs[InputUsed[1]];
6179 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6186 MI.eraseFromParent();
6199 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6205 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6208 const unsigned NumParts =
6210 : SrcTy.getNumElements();
6214 if (DstTy != NarrowTy)
6220 unsigned NumPartsLeft = NumParts;
6221 while (NumPartsLeft > 1) {
6222 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6225 .buildInstr(ScalarOpc, {NarrowTy},
6226 {SplitSrcs[Idx], SplitSrcs[Idx + 1]},
6230 SplitSrcs = PartialResults;
6231 PartialResults.
clear();
6232 NumPartsLeft = SplitSrcs.
size();
6236 MI.eraseFromParent();
6241 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6243 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]},
6247 MI.eraseFromParent();
6251 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6253 .buildInstr(RdxMI.getOpcode(), {DstTy},
6263 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6266 Register Acc = PartialReductions[0];
6267 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6268 if (Part == NumParts - 1) {
6269 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, {Acc, PartialReductions[Part]},
6273 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]},
6278 MI.eraseFromParent();
6284 unsigned int TypeIdx,
6286 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6287 MI.getFirst3RegLLTs();
6288 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6292 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6293 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6294 "Unexpected vecreduce opcode");
6295 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6296 ? TargetOpcode::G_FADD
6297 : TargetOpcode::G_FMUL;
6300 unsigned NumParts = SrcTy.getNumElements();
6303 for (
unsigned i = 0; i < NumParts; i++)
6305 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]},
6310 MI.eraseFromParent();
6317 unsigned ScalarOpc) {
6325 while (SplitSrcs.
size() > 1) {
6327 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6337 SplitSrcs = std::move(PartialRdxs);
6341 MI.getOperand(1).setReg(SplitSrcs[0]);
6348 const LLT HalfTy,
const LLT AmtTy) {
6350 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6351 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6355 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6356 MI.eraseFromParent();
6362 unsigned VTBits = 2 * NVTBits;
6365 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6366 if (Amt.
ugt(VTBits)) {
6368 }
else if (Amt.
ugt(NVTBits)) {
6371 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6372 }
else if (Amt == NVTBits) {
6380 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6383 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6384 if (Amt.
ugt(VTBits)) {
6386 }
else if (Amt.
ugt(NVTBits)) {
6388 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6390 }
else if (Amt == NVTBits) {
6394 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6396 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6398 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6404 if (Amt.
ugt(VTBits)) {
6406 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6407 }
else if (Amt.
ugt(NVTBits)) {
6409 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6411 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6412 }
else if (Amt == NVTBits) {
6415 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6417 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6419 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6421 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6428 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6429 MI.eraseFromParent();
6445 LLT DstTy = MRI.getType(DstReg);
6450 LLT ShiftAmtTy = MRI.getType(Amt);
6452 if (DstEltSize % 2 != 0)
6468 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6479 const unsigned NewBitSize = DstEltSize / 2;
6491 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6493 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6494 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6497 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6498 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6500 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6505 switch (
MI.getOpcode()) {
6506 case TargetOpcode::G_SHL: {
6508 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6510 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6511 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6512 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6515 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6516 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6518 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6520 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6522 ResultRegs[0] =
Lo.getReg(0);
6523 ResultRegs[1] =
Hi.getReg(0);
6526 case TargetOpcode::G_LSHR:
6527 case TargetOpcode::G_ASHR: {
6529 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6531 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6532 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6533 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6537 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6540 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6541 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6543 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6547 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6549 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6551 ResultRegs[0] =
Lo.getReg(0);
6552 ResultRegs[1] =
Hi.getReg(0);
6559 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6560 MI.eraseFromParent();
6569 LLT TargetTy,
LLT ShiftAmtTy) {
6572 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6574 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6575 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6576 const bool NeedsInterWordShift = ShiftBits != 0;
6579 case TargetOpcode::G_SHL: {
6582 if (PartIdx < ShiftWords)
6585 unsigned SrcIdx = PartIdx - ShiftWords;
6586 if (!NeedsInterWordShift)
6587 return SrcParts[SrcIdx];
6592 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6596 return Hi.getReg(0);
6599 case TargetOpcode::G_LSHR: {
6600 unsigned SrcIdx = PartIdx + ShiftWords;
6601 if (SrcIdx >= NumParts)
6603 if (!NeedsInterWordShift)
6604 return SrcParts[SrcIdx];
6608 if (SrcIdx + 1 < NumParts) {
6609 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6613 return Lo.getReg(0);
6616 case TargetOpcode::G_ASHR: {
6618 unsigned SrcIdx = PartIdx + ShiftWords;
6619 if (SrcIdx >= NumParts)
6621 if (!NeedsInterWordShift)
6622 return SrcParts[SrcIdx];
6627 (SrcIdx == NumParts - 1)
6631 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6653 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6654 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6659 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6668 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6669 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6671 auto IsZeroBitShift =
6679 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6680 : TargetOpcode::G_SHL;
6683 auto TargetBitsConst =
6685 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6690 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6695 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6697 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6701 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6714 LLT DstTy = MRI.getType(DstReg);
6718 const unsigned NumParts = DstBits / TargetBits;
6720 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6730 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6731 MI.eraseFromParent();
6736 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6737 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6743 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6747 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6750 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6751 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6755 for (
unsigned I = 0;
I < NumParts; ++
I)
6757 Params, TargetTy, ShiftAmtTy);
6759 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6760 MI.eraseFromParent();
6769 LLT DstTy = MRI.getType(DstReg);
6770 LLT ShiftAmtTy = MRI.getType(AmtReg);
6774 const unsigned NumParts = DstBits / TargetBits;
6776 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6793 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6805 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6806 auto TargetBitsLog2Const =
6807 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6808 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6811 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6813 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6821 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6822 auto TargetBitsMinusOneConst =
6823 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6825 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6826 TargetBitsMinusOneConst)
6829 FillValue = ZeroReg;
6837 for (
unsigned I = 0;
I < NumParts; ++
I) {
6839 Register InBoundsResult = FillValue;
6849 for (
unsigned K = 0;
K < NumParts; ++
K) {
6850 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy,
K);
6852 WordShift, WordShiftKConst);
6864 switch (
MI.getOpcode()) {
6865 case TargetOpcode::G_SHL:
6866 MainSrcIdx = (int)
I - (
int)
K;
6867 CarrySrcIdx = MainSrcIdx - 1;
6869 case TargetOpcode::G_LSHR:
6870 case TargetOpcode::G_ASHR:
6871 MainSrcIdx = (int)
I + (
int)
K;
6872 CarrySrcIdx = MainSrcIdx + 1;
6880 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6881 Register MainOp = SrcParts[MainSrcIdx];
6885 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6886 CarryOp = SrcParts[CarrySrcIdx];
6887 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6888 CarrySrcIdx >= (
int)NumParts)
6889 CarryOp = FillValue;
6895 ResultForK = FillValue;
6901 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6908 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6912 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6913 MI.eraseFromParent();
6920 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6923 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6938 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6943 "getNeutralElementForVecReduce called with invalid opcode!");
6944 case TargetOpcode::G_VECREDUCE_ADD:
6945 case TargetOpcode::G_VECREDUCE_OR:
6946 case TargetOpcode::G_VECREDUCE_XOR:
6947 case TargetOpcode::G_VECREDUCE_UMAX:
6949 case TargetOpcode::G_VECREDUCE_MUL:
6951 case TargetOpcode::G_VECREDUCE_AND:
6952 case TargetOpcode::G_VECREDUCE_UMIN:
6955 case TargetOpcode::G_VECREDUCE_SMAX:
6958 case TargetOpcode::G_VECREDUCE_SMIN:
6961 case TargetOpcode::G_VECREDUCE_FADD:
6963 case TargetOpcode::G_VECREDUCE_FMUL:
6965 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6966 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6967 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6968 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6976 unsigned Opc =
MI.getOpcode();
6978 case TargetOpcode::G_IMPLICIT_DEF:
6979 case TargetOpcode::G_LOAD: {
6987 case TargetOpcode::G_STORE:
6994 case TargetOpcode::G_AND:
6995 case TargetOpcode::G_OR:
6996 case TargetOpcode::G_XOR:
6997 case TargetOpcode::G_ADD:
6998 case TargetOpcode::G_SUB:
6999 case TargetOpcode::G_MUL:
7000 case TargetOpcode::G_FADD:
7001 case TargetOpcode::G_FSUB:
7002 case TargetOpcode::G_FMUL:
7003 case TargetOpcode::G_FDIV:
7004 case TargetOpcode::G_FCOPYSIGN:
7005 case TargetOpcode::G_UADDSAT:
7006 case TargetOpcode::G_USUBSAT:
7007 case TargetOpcode::G_SADDSAT:
7008 case TargetOpcode::G_SSUBSAT:
7009 case TargetOpcode::G_SMIN:
7010 case TargetOpcode::G_SMAX:
7011 case TargetOpcode::G_UMIN:
7012 case TargetOpcode::G_UMAX:
7013 case TargetOpcode::G_FMINNUM:
7014 case TargetOpcode::G_FMAXNUM:
7015 case TargetOpcode::G_FMINNUM_IEEE:
7016 case TargetOpcode::G_FMAXNUM_IEEE:
7017 case TargetOpcode::G_FMINIMUM:
7018 case TargetOpcode::G_FMAXIMUM:
7019 case TargetOpcode::G_FMINIMUMNUM:
7020 case TargetOpcode::G_FMAXIMUMNUM:
7021 case TargetOpcode::G_STRICT_FADD:
7022 case TargetOpcode::G_STRICT_FSUB:
7023 case TargetOpcode::G_STRICT_FMUL: {
7031 case TargetOpcode::G_SHL:
7032 case TargetOpcode::G_ASHR:
7033 case TargetOpcode::G_LSHR: {
7039 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
7045 case TargetOpcode::G_FMA:
7046 case TargetOpcode::G_STRICT_FMA:
7047 case TargetOpcode::G_FSHR:
7048 case TargetOpcode::G_FSHL: {
7057 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
7058 case TargetOpcode::G_EXTRACT:
7065 case TargetOpcode::G_INSERT:
7066 case TargetOpcode::G_INSERT_VECTOR_ELT:
7067 case TargetOpcode::G_FREEZE:
7068 case TargetOpcode::G_FNEG:
7069 case TargetOpcode::G_FABS:
7070 case TargetOpcode::G_FSQRT:
7071 case TargetOpcode::G_FCEIL:
7072 case TargetOpcode::G_FFLOOR:
7073 case TargetOpcode::G_FNEARBYINT:
7074 case TargetOpcode::G_FRINT:
7075 case TargetOpcode::G_INTRINSIC_ROUND:
7076 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7077 case TargetOpcode::G_INTRINSIC_TRUNC:
7078 case TargetOpcode::G_BITREVERSE:
7079 case TargetOpcode::G_BSWAP:
7080 case TargetOpcode::G_FCANONICALIZE:
7081 case TargetOpcode::G_SEXT_INREG:
7082 case TargetOpcode::G_ABS:
7083 case TargetOpcode::G_CTLZ:
7084 case TargetOpcode::G_CTPOP:
7092 case TargetOpcode::G_SELECT: {
7093 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7095 if (!CondTy.isScalar() ||
7101 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7103 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7108 if (CondTy.isVector())
7118 case TargetOpcode::G_UNMERGE_VALUES:
7120 case TargetOpcode::G_PHI:
7122 case TargetOpcode::G_SHUFFLE_VECTOR:
7124 case TargetOpcode::G_BUILD_VECTOR: {
7126 for (
auto Op :
MI.uses()) {
7134 MIRBuilder.buildDeleteTrailingVectorElements(
7135 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7136 MI.eraseFromParent();
7139 case TargetOpcode::G_SEXT:
7140 case TargetOpcode::G_ZEXT:
7141 case TargetOpcode::G_ANYEXT:
7142 case TargetOpcode::G_TRUNC:
7143 case TargetOpcode::G_FPTRUNC:
7144 case TargetOpcode::G_FPEXT:
7145 case TargetOpcode::G_FPTOSI:
7146 case TargetOpcode::G_FPTOUI:
7147 case TargetOpcode::G_FPTOSI_SAT:
7148 case TargetOpcode::G_FPTOUI_SAT:
7149 case TargetOpcode::G_SITOFP:
7150 case TargetOpcode::G_UITOFP:
7151 case TargetOpcode::G_TRUNC_SSAT_S:
7152 case TargetOpcode::G_TRUNC_SSAT_U:
7153 case TargetOpcode::G_TRUNC_USAT_U: {
7160 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7163 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7171 case TargetOpcode::G_ICMP:
7172 case TargetOpcode::G_FCMP: {
7180 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7185 case TargetOpcode::G_BITCAST: {
7189 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7190 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7206 case TargetOpcode::G_VECREDUCE_FADD:
7207 case TargetOpcode::G_VECREDUCE_FMUL:
7208 case TargetOpcode::G_VECREDUCE_ADD:
7209 case TargetOpcode::G_VECREDUCE_MUL:
7210 case TargetOpcode::G_VECREDUCE_AND:
7211 case TargetOpcode::G_VECREDUCE_OR:
7212 case TargetOpcode::G_VECREDUCE_XOR:
7213 case TargetOpcode::G_VECREDUCE_SMAX:
7214 case TargetOpcode::G_VECREDUCE_SMIN:
7215 case TargetOpcode::G_VECREDUCE_UMAX:
7216 case TargetOpcode::G_VECREDUCE_UMIN: {
7217 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7219 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7220 auto NeutralElement = getNeutralElementForVecReduce(
7226 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7227 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7228 NeutralElement, Idx);
7232 MO.
setReg(NewVec.getReg(0));
7244 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7246 unsigned MaskNumElts = Mask.size();
7247 unsigned SrcNumElts = SrcTy.getNumElements();
7250 if (MaskNumElts == SrcNumElts)
7253 if (MaskNumElts < SrcNumElts) {
7261 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7262 MI.getOperand(1).getReg(),
7263 MI.getOperand(2).getReg(), NewMask);
7264 MI.eraseFromParent();
7269 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7270 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7279 MOps1[0] =
MI.getOperand(1).getReg();
7280 MOps2[0] =
MI.getOperand(2).getReg();
7282 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7283 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7287 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7289 if (Idx >=
static_cast<int>(SrcNumElts))
7290 Idx += PaddedMaskNumElts - SrcNumElts;
7295 if (MaskNumElts != PaddedMaskNumElts) {
7297 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7300 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7302 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7307 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7310 MI.eraseFromParent();
7316 unsigned int TypeIdx,
LLT MoreTy) {
7317 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7319 unsigned NumElts = DstTy.getNumElements();
7322 if (DstTy.isVector() && Src1Ty.isVector() &&
7323 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7331 if (DstTy != Src1Ty || DstTy != Src2Ty)
7339 for (
unsigned I = 0;
I != NumElts; ++
I) {
7341 if (Idx <
static_cast<int>(NumElts))
7344 NewMask[
I] = Idx - NumElts + WidenNumElts;
7348 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7349 MI.getOperand(1).getReg(),
7350 MI.getOperand(2).getReg(), NewMask);
7351 MI.eraseFromParent();
7360 unsigned SrcParts = Src1Regs.
size();
7361 unsigned DstParts = DstRegs.
size();
7363 unsigned DstIdx = 0;
7365 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7366 DstRegs[DstIdx] = FactorSum;
7371 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7373 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7374 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7376 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7382 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7383 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7384 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7385 unsigned i = RevI - 1;
7387 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7397 if (DstIdx != DstParts - 1) {
7398 MachineInstrBuilder Uaddo =
7399 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7400 FactorSum = Uaddo.
getReg(0);
7401 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7402 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7403 MachineInstrBuilder Uaddo =
7404 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7405 FactorSum = Uaddo.
getReg(0);
7406 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7407 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7411 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7412 for (
unsigned i = 2; i < Factors.
size(); ++i)
7413 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7416 CarrySumPrevDstIdx = CarrySum;
7417 DstRegs[DstIdx] = FactorSum;
7429 LLT DstType = MRI.getType(DstReg);
7431 if (DstType.isVector())
7434 unsigned Opcode =
MI.getOpcode();
7435 unsigned OpO, OpE, OpF;
7437 case TargetOpcode::G_SADDO:
7438 case TargetOpcode::G_SADDE:
7439 case TargetOpcode::G_UADDO:
7440 case TargetOpcode::G_UADDE:
7441 case TargetOpcode::G_ADD:
7442 OpO = TargetOpcode::G_UADDO;
7443 OpE = TargetOpcode::G_UADDE;
7444 OpF = TargetOpcode::G_UADDE;
7445 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7446 OpF = TargetOpcode::G_SADDE;
7448 case TargetOpcode::G_SSUBO:
7449 case TargetOpcode::G_SSUBE:
7450 case TargetOpcode::G_USUBO:
7451 case TargetOpcode::G_USUBE:
7452 case TargetOpcode::G_SUB:
7453 OpO = TargetOpcode::G_USUBO;
7454 OpE = TargetOpcode::G_USUBE;
7455 OpF = TargetOpcode::G_USUBE;
7456 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7457 OpF = TargetOpcode::G_SSUBE;
7464 unsigned NumDefs =
MI.getNumExplicitDefs();
7465 Register Src1 =
MI.getOperand(NumDefs).getReg();
7466 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7469 CarryDst =
MI.getOperand(1).getReg();
7470 if (
MI.getNumOperands() == NumDefs + 3)
7471 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7473 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7474 LLT LeftoverTy, DummyTy;
7476 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7481 int NarrowParts = Src1Regs.
size();
7482 Src1Regs.
append(Src1Left);
7483 Src2Regs.
append(Src2Left);
7486 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7488 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7491 if (i == e - 1 && CarryDst)
7492 CarryOut = CarryDst;
7494 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7497 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7498 {Src1Regs[i], Src2Regs[i]});
7499 }
else if (i == e - 1) {
7500 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7501 {Src1Regs[i], Src2Regs[i], CarryIn});
7503 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7504 {Src1Regs[i], Src2Regs[i], CarryIn});
7510 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7511 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7512 ArrayRef(DstRegs).drop_front(NarrowParts));
7514 MI.eraseFromParent();
7520 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7522 LLT Ty = MRI.getType(DstReg);
7526 unsigned Size = Ty.getSizeInBits();
7528 if (
Size % NarrowSize != 0)
7531 unsigned NumParts =
Size / NarrowSize;
7532 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7533 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7539 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7543 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7544 MI.eraseFromParent();
7554 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7557 LLT SrcTy = MRI.getType(Src);
7569 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7582 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7585 if (SizeOp1 % NarrowSize != 0)
7587 int NumParts = SizeOp1 / NarrowSize;
7590 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7594 uint64_t OpStart =
MI.getOperand(2).getImm();
7595 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7596 for (
int i = 0; i < NumParts; ++i) {
7597 unsigned SrcStart = i * NarrowSize;
7599 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7602 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7610 int64_t ExtractOffset;
7612 if (OpStart < SrcStart) {
7614 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7616 ExtractOffset = OpStart - SrcStart;
7617 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7621 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7623 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7624 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7631 if (MRI.getType(DstReg).isVector())
7632 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7633 else if (DstRegs.
size() > 1)
7634 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7637 MI.eraseFromParent();
7649 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7651 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7654 SrcRegs.
append(LeftoverRegs);
7658 uint64_t OpStart =
MI.getOperand(3).getImm();
7659 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7660 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7661 unsigned DstStart =
I * NarrowSize;
7663 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7671 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7673 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7677 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7685 int64_t ExtractOffset, InsertOffset;
7687 if (OpStart < DstStart) {
7689 ExtractOffset = DstStart - OpStart;
7690 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7692 InsertOffset = OpStart - DstStart;
7694 SegSize = std::min(NarrowSize - InsertOffset, OpSize);
7698 if (ExtractOffset != 0 || SegSize != OpSize) {
7700 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7701 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7704 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7705 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7709 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7713 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7716 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7718 MI.eraseFromParent();
7726 LLT DstTy = MRI.getType(DstReg);
7728 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7734 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7735 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7739 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7740 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7743 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7744 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7745 {Src0Regs[I], Src1Regs[I]});
7749 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7752 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7753 DstLeftoverRegs.
push_back(Inst.getReg(0));
7756 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7757 LeftoverTy, DstLeftoverRegs);
7759 MI.eraseFromParent();
7769 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7771 LLT DstTy = MRI.getType(DstReg);
7776 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7777 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7778 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7780 MI.eraseFromParent();
7790 Register CondReg =
MI.getOperand(1).getReg();
7791 LLT CondTy = MRI.getType(CondReg);
7792 if (CondTy.isVector())
7796 LLT DstTy = MRI.getType(DstReg);
7802 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7803 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7807 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7808 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7811 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7813 CondReg, Src1Regs[
I], Src2Regs[
I]);
7817 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7819 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7823 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7824 LeftoverTy, DstLeftoverRegs);
7826 MI.eraseFromParent();
7836 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7839 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7840 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7843 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7845 auto C_0 =
B.buildConstant(NarrowTy, 0);
7847 UnmergeSrc.getReg(1), C_0);
7848 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7849 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7850 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7851 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7852 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7853 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7855 MI.eraseFromParent();
7868 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7871 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7872 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7875 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7877 auto C_0 =
B.buildConstant(NarrowTy, 0);
7879 UnmergeSrc.getReg(0), C_0);
7880 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7881 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7882 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7883 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7884 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7885 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7887 MI.eraseFromParent();
7900 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7903 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7908 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7912 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7913 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7921 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7922 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7925 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7926 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7928 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7930 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7932 MI.eraseFromParent();
7942 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7945 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7946 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7948 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7949 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7950 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7952 MI.eraseFromParent();
7967 LLT ExpTy = MRI.getType(ExpReg);
7972 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7973 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7974 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7975 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7977 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7979 MI.getOperand(2).setReg(Trunc.getReg(0));
7986 unsigned Opc =
MI.getOpcode();
7989 auto QAction = LI.getAction(Q).Action;
7995 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7998 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
8002 case TargetOpcode::G_CTLZ: {
8003 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8004 unsigned Len = SrcTy.getScalarSizeInBits();
8006 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
8008 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
8009 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
8012 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8013 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
8014 MI.eraseFromParent();
8030 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
8031 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
8034 Op = MIBOp.getReg(0);
8039 MI.eraseFromParent();
8042 case TargetOpcode::G_CTTZ_ZERO_POISON: {
8045 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
8049 case TargetOpcode::G_CTTZ: {
8050 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8052 unsigned Len = SrcTy.getScalarSizeInBits();
8053 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
8056 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
8057 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
8060 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8061 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
8062 MI.eraseFromParent();
8069 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8070 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8072 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8073 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8074 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8075 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8078 MI.eraseFromParent();
8082 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8083 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8087 case TargetOpcode::G_CTPOP: {
8089 LLT Ty = MRI.getType(SrcReg);
8090 unsigned Size = Ty.getScalarSizeInBits();
8102 auto C_1 =
B.buildConstant(Ty, 1);
8103 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8105 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8106 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8107 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8111 auto C_2 =
B.buildConstant(Ty, 2);
8112 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8114 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8115 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8116 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8117 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8124 auto C_4 =
B.buildConstant(Ty, 4);
8125 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8126 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8128 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8129 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8131 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8134 if (
Size == 16 && !Ty.isVector()) {
8136 auto C_8 =
B.buildConstant(Ty, 8);
8137 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8138 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8139 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8140 MI.eraseFromParent();
8149 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8151 auto IsMulSupported = [
this](
const LLT Ty) {
8152 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8155 if (IsMulSupported(Ty)) {
8156 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8157 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8159 auto ResTmp = B8Count;
8160 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8161 auto ShiftC =
B.buildConstant(Ty, Shift);
8162 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8163 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8165 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8167 MI.eraseFromParent();
8170 case TargetOpcode::G_CTLS: {
8171 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8175 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8176 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8178 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8184 MI.eraseFromParent();
8214 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8215 LLT Ty = MRI.getType(Dst);
8216 LLT ShTy = MRI.getType(Z);
8223 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8224 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8229 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8230 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8234 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8247 MI.eraseFromParent();
8253 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8254 LLT Ty = MRI.getType(Dst);
8255 LLT ShTy = MRI.getType(Z);
8258 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8272 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8273 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8274 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8275 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8276 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8282 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8285 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8288 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8290 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8291 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8292 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8295 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8297 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8299 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8302 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8303 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8308 MI.eraseFromParent();
8319 LLT Ty = MRI.getType(Dst);
8320 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8322 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8323 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8326 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8327 return lowerFunnelShiftAsShifts(
MI);
8331 if (Result == UnableToLegalize)
8332 return lowerFunnelShiftAsShifts(
MI);
8337 auto [Dst, Src] =
MI.getFirst2Regs();
8338 LLT DstTy = MRI.getType(Dst);
8339 LLT SrcTy = MRI.getType(Src);
8343 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8351 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8355 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8359 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8364 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8365 {UnmergeSrc.getReg(0)});
8366 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8367 {UnmergeSrc.getReg(1)});
8370 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8372 MI.eraseFromParent();
8389 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8393 LLT DstTy = MRI.getType(DstReg);
8394 LLT SrcTy = MRI.getType(SrcReg);
8402 SrcTy.getElementCount().divideCoefficientBy(2));
8415 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8427 MI.eraseFromParent();
8436 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8437 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8438 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8439 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8440 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8441 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8442 MI.eraseFromParent();
8447 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8449 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8450 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8455 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8456 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8458 return lowerRotateWithReverseRotate(
MI);
8461 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8462 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8463 bool IsFShLegal =
false;
8464 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8465 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8469 MI.eraseFromParent();
8474 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8477 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8482 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8483 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8484 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8495 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8496 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8498 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8505 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8506 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8508 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8510 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8514 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal, OrFlags);
8515 MI.eraseFromParent();
8523 auto [Dst, Src] =
MI.getFirst2Regs();
8528 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8541 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8543 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8548 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8550 MI.eraseFromParent();
8558 auto [Dst, Src] =
MI.getFirst2Regs();
8562 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8573 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8574 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8576 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8583 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8584 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8585 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8587 MI.eraseFromParent();
8598 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8599 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8605 MI.eraseFromParent();
8610 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8616 MI.eraseFromParent();
8620 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8640 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8650 MI.eraseFromParent();
8654 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8660 if (DstTy.getScalarSizeInBits() == 32) {
8667 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8668 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8670 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8677 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8678 MI.eraseFromParent();
8686 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8690 if (SrcTy !=
S64 && SrcTy !=
S32)
8692 if (DstTy !=
S32 && DstTy !=
S64)
8719 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8721 MI.eraseFromParent();
8726 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8731 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8738 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8740 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8741 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8743 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8744 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8746 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8748 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8749 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8750 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8753 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8754 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8755 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8757 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask,
K);
8760 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8765 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8766 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8772 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8774 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8775 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8777 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8782 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8783 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8785 MI.eraseFromParent();
8791 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8793 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8794 unsigned SatWidth = DstTy.getScalarSizeInBits();
8798 APInt MinInt, MaxInt;
8821 if (AreExactFloatBounds) {
8823 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8826 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8828 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8837 MI.eraseFromParent();
8842 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8847 MI.eraseFromParent();
8854 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8862 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8872 MI.eraseFromParent();
8878 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8882 MI.eraseFromParent();
8889 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8890 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8891 "Only G_FPEXT and G_FPTRUNC are expected");
8893 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8898 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8900 StoreOpc = TargetOpcode::G_STORE;
8901 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8904 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8905 LoadOpc = TargetOpcode::G_LOAD;
8914 StackTy, StackTyAlign);
8915 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8918 StackTy, StackTyAlign);
8919 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8921 MI.eraseFromParent();
8929 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8930 assert(SrcTy.getScalarType().isBFloat16() &&
8931 "expected a bf16 source for bf16 fpext lowering");
8942 if (DstTy.getScalarType().isFloat32())
8947 MI.eraseFromParent();
8952 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8953 if (SrcTy.getScalarType().isBFloat16() &&
8954 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8966 auto [Dst, Src] =
MI.getFirst2Regs();
8970 if (MRI.getType(Src).isVector())
8974 unsigned Flags =
MI.getFlags();
8977 MI.eraseFromParent();
8981 const unsigned ExpMask = 0x7ff;
8982 const unsigned ExpBiasf64 = 1023;
8983 const unsigned ExpBiasf16 = 15;
8985 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8995 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
9002 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
9004 auto Zero =
MIRBuilder.buildConstant(I32, 0);
9006 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
9010 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
9012 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
9014 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
9015 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
9023 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
9024 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
9035 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9046 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9062 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9072 MI.eraseFromParent();
9079 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9087 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9113 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9115 MI.eraseFromParent();
9124 LLT OperandTy = MRI.getType(
Op);
9134 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9136 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9137 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9138 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9139 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9140 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9148 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9151 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9153 AbsWide, AbsNarrowAsWide);
9157 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9158 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9160 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9161 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9167 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9173 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9174 MI.eraseFromParent();
9180 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9181 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9184 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9187 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9194 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9195 LLT Ty = MRI.getType(Dst);
9197 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9198 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9199 MI.eraseFromParent();
9204 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9205 LLT Ty = MRI.getType(Src);
9206 auto Flags =
MI.getFlags();
9214 FracToUse = FracPart.getReg(0);
9216 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9220 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9222 FracToUse =
Select.getReg(0);
9225 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9228 MI.eraseFromParent();
9234 case TargetOpcode::G_SMIN:
9236 case TargetOpcode::G_SMAX:
9238 case TargetOpcode::G_UMIN:
9240 case TargetOpcode::G_UMAX:
9248 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9253 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9254 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9256 MI.eraseFromParent();
9265 LLT DstTy = MRI.getType(Dst);
9266 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9276 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9277 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9279 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9282 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9283 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9284 if (TLI.preferSelectsOverBooleanArithmetic(
9287 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9288 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9290 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9291 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9297 unsigned BoolExtOp =
9299 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9300 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9304 MI.eraseFromParent();
9310 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9311 const int Src0Size = Src0Ty.getScalarSizeInBits();
9312 const int Src1Size = Src1Ty.getScalarSizeInBits();
9322 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9323 Src0Ty.getScalarType().isInteger()))
9324 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9326 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9327 Src1Ty.getScalarType().isInteger()))
9328 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9333 auto NotSignBitMask =
MIRBuilder.buildConstant(
9337 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9339 if (Src0Ty == Src1Ty) {
9340 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9341 }
else if (Src0Size > Src1Size) {
9342 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9343 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9344 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9345 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9347 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9348 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9349 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9350 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9356 unsigned Flags =
MI.getFlags();
9361 if (DstTy == DstIntTy)
9362 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9368 MI.eraseFromParent();
9379 switch (
MI.getOpcode()) {
9380 case TargetOpcode::G_FMINNUM:
9381 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9383 case TargetOpcode::G_FMINIMUMNUM:
9384 NewOp = TargetOpcode::G_FMINNUM;
9386 case TargetOpcode::G_FMAXNUM:
9387 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9389 case TargetOpcode::G_FMAXIMUMNUM:
9390 NewOp = TargetOpcode::G_FMAXNUM;
9396 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9397 LLT Ty = MRI.getType(Dst);
9406 if (!VT->isKnownNeverSNaN(Src0))
9407 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9409 if (!VT->isKnownNeverSNaN(Src1))
9410 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9415 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9416 MI.eraseFromParent();
9422 unsigned Opc =
MI.getOpcode();
9423 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9424 LLT Ty = MRI.getType(Dst);
9427 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9429 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9430 unsigned OpcNonIeee =
9431 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9432 bool MinMaxMustRespectOrderedZero =
false;
9436 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9438 MinMaxMustRespectOrderedZero =
true;
9439 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9444 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9449 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9452 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9456 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9458 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9470 const unsigned Flags =
MI.getFlags();
9476 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9478 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9480 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9482 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9484 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9489 MI.eraseFromParent();
9496 LLT Ty = MRI.getType(DstReg);
9497 unsigned Flags =
MI.getFlags();
9502 MI.eraseFromParent();
9508 auto [DstReg,
X] =
MI.getFirst2Regs();
9509 const unsigned Flags =
MI.getFlags();
9510 const LLT Ty = MRI.getType(DstReg);
9522 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9524 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9529 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9530 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9531 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9532 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9534 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9536 MI.eraseFromParent();
9541 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9542 unsigned Flags =
MI.getFlags();
9543 LLT Ty = MRI.getType(DstReg);
9550 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9551 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9554 SrcReg, Zero, Flags);
9556 SrcReg, Trunc, Flags);
9560 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9561 MI.eraseFromParent();
9567 const unsigned NumOps =
MI.getNumOperands();
9568 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9569 unsigned PartSize = Src0Ty.getSizeInBits();
9574 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9575 const unsigned Offset = (
I - 1) * PartSize;
9578 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9581 MRI.createGenericVirtualRegister(WideTy);
9584 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9585 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9586 ResultReg = NextResult;
9589 if (DstTy.isPointer()) {
9590 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9591 DstTy.getAddressSpace())) {
9597 }
else if (WideTy != DstTy) {
9601 MI.eraseFromParent();
9607 const unsigned NumDst =
MI.getNumOperands() - 1;
9608 Register SrcReg =
MI.getOperand(NumDst).getReg();
9609 Register Dst0Reg =
MI.getOperand(0).getReg();
9610 LLT DstTy = MRI.getType(Dst0Reg);
9619 LLT IntTy = MRI.getType(SrcReg);
9624 unsigned Offset = DstSize;
9625 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9627 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9631 MI.eraseFromParent();
9650 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9651 InsertVal =
MI.getOperand(2).getReg();
9653 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9655 LLT VecTy = MRI.getType(SrcVec);
9665 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9666 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9668 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9671 MI.eraseFromParent();
9676 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9687 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9694 int64_t
Offset = IdxVal * EltBytes;
9705 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9708 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9710 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9713 MI.eraseFromParent();
9719 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9720 MI.getFirst3RegLLTs();
9730 for (
int Idx : Mask) {
9732 if (!
Undef.isValid())
9738 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9740 int NumElts = Src0Ty.getNumElements();
9741 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9742 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9743 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9745 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9747 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9752 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9753 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9754 MI.eraseFromParent();
9760 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9761 MI.getFirst4RegLLTs();
9763 if (VecTy.isScalableVector())
9779 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9784 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9787 std::optional<APInt> PassthruSplatVal =
9790 if (PassthruSplatVal.has_value()) {
9792 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9793 }
else if (HasPassthru) {
9794 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9795 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9801 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9805 unsigned NumElmts = VecTy.getNumElements();
9806 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9808 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9811 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9814 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9819 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9821 if (HasPassthru &&
I == NumElmts - 1) {
9824 auto AllLanesSelected =
MIRBuilder.buildICmp(
9826 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9827 {OutPos, EndOfVector});
9831 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9833 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9838 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9840 MI.eraseFromParent();
9857 if (Alignment >
Align(1)) {
9858 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9869 const auto &MF = *
MI.getMF();
9875 Register AllocSize =
MI.getOperand(1).getReg();
9878 LLT PtrTy = MRI.getType(Dst);
9879 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9886 MI.eraseFromParent();
9892 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9897 MI.eraseFromParent();
9903 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9908 MI.eraseFromParent();
9914 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9915 unsigned Offset =
MI.getOperand(2).getImm();
9918 if (SrcTy.isVector()) {
9919 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9920 unsigned DstSize = DstTy.getSizeInBits();
9922 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9923 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9925 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9929 for (
unsigned Idx =
Offset / SrcEltSize;
9930 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9931 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9933 if (SubVectorElts.
size() == 1)
9934 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9936 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9938 MI.eraseFromParent();
9944 if ((SrcTy.isPointer() &&
9945 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9946 (DstTy.isPointer() &&
9947 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9948 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9952 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9953 (SrcTy.isScalar() || SrcTy.isPointer() ||
9954 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9955 LLT SrcIntTy = SrcTy;
9956 if (!SrcTy.isScalar()) {
9958 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9962 if (DstTy.isPointer())
9964 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9970 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9974 if (DstTy.isPointer())
9977 MI.eraseFromParent();
9985 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9986 uint64_t
Offset =
MI.getOperand(3).getImm();
9988 LLT DstTy = MRI.getType(Src);
9989 LLT InsertTy = MRI.getType(InsertSrc);
9992 bool IsNonIntegralInsert =
10002 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
10003 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10010 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
10012 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
10016 for (; Idx <
Offset / EltSize; ++Idx) {
10017 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10022 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
10023 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
10025 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
10029 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
10031 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
10038 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10041 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
10042 MI.eraseFromParent();
10051 if (IsNonIntegralDst || IsNonIntegralInsert) {
10052 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10056 LLT IntDstTy = DstTy;
10060 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
10065 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
10071 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10077 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10078 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10079 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10082 MI.eraseFromParent();
10088 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10089 MI.getFirst4RegLLTs();
10090 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10093 LLT BoolTy = Dst1Ty;
10095 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10104 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10110 auto ResultLowerThanLHS =
10114 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10118 auto LHSLessThanRHS =
10120 auto ResultNegative =
10122 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10126 MI.eraseFromParent();
10132 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10133 const LLT Ty = MRI.getType(Res);
10136 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10137 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10138 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10142 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10143 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10146 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10149 MI.eraseFromParent();
10154 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10155 const LLT Ty = MRI.getType(Res);
10158 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10159 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10160 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10164 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10165 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10167 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10170 MI.eraseFromParent();
10176 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10177 LLT Ty = MRI.getType(Res);
10181 switch (
MI.getOpcode()) {
10184 case TargetOpcode::G_UADDSAT:
10187 BaseOp = TargetOpcode::G_ADD;
10189 case TargetOpcode::G_SADDSAT:
10192 BaseOp = TargetOpcode::G_ADD;
10194 case TargetOpcode::G_USUBSAT:
10197 BaseOp = TargetOpcode::G_SUB;
10199 case TargetOpcode::G_SSUBSAT:
10202 BaseOp = TargetOpcode::G_SUB;
10217 uint64_t NumBits = Ty.getScalarSizeInBits();
10224 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10228 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10236 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10241 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10242 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10245 MI.eraseFromParent();
10251 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10252 LLT Ty = MRI.getType(Res);
10256 unsigned OverflowOp;
10257 switch (
MI.getOpcode()) {
10260 case TargetOpcode::G_UADDSAT:
10263 OverflowOp = TargetOpcode::G_UADDO;
10265 case TargetOpcode::G_SADDSAT:
10268 OverflowOp = TargetOpcode::G_SADDO;
10270 case TargetOpcode::G_USUBSAT:
10273 OverflowOp = TargetOpcode::G_USUBO;
10275 case TargetOpcode::G_SSUBSAT:
10278 OverflowOp = TargetOpcode::G_SSUBO;
10283 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10284 Register Tmp = OverflowRes.getReg(0);
10285 Register Ov = OverflowRes.getReg(1);
10294 uint64_t NumBits = Ty.getScalarSizeInBits();
10295 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10296 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10299 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10307 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10309 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10311 MI.eraseFromParent();
10317 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10318 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10319 "Expected shlsat opcode!");
10320 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10321 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10322 LLT Ty = MRI.getType(Res);
10326 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10327 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10336 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10341 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10343 MI.eraseFromParent();
10349 unsigned Opc =
MI.getOpcode();
10350 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10351 unsigned DstSize = DstTy.getScalarSizeInBits();
10352 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10354 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10357 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10360 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10361 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10364 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10365 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10368 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10370 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10376 MI.eraseFromParent();
10381 auto [Dst, Src] =
MI.getFirst2Regs();
10382 const LLT Ty = MRI.getType(Src);
10383 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10384 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10387 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10388 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10389 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10390 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10393 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10396 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10397 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10399 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10400 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10401 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10403 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10404 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10405 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10407 Res.getInstr()->getOperand(0).setReg(Dst);
10409 MI.eraseFromParent();
10416 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10419 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10420 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10421 return B.buildOr(Dst,
LHS,
RHS);
10426 auto [Dst, Src] =
MI.getFirst2Regs();
10427 const LLT SrcTy = MRI.getType(Src);
10428 unsigned Size = SrcTy.getScalarSizeInBits();
10429 unsigned VSize = SrcTy.getSizeInBits();
10432 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10433 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10434 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10435 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10440 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10441 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10442 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10446 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10469 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10473 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10476 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10480 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10484 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10489 MI.eraseFromParent();
10497 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10498 int NameOpIdx = IsRead ? 1 : 0;
10499 int ValRegIndex = IsRead ? 0 : 1;
10501 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10502 const LLT Ty = MRI.getType(ValReg);
10504 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10511 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10512 Fn,
MI.getDebugLoc()));
10516 MI.eraseFromParent();
10525 MI.eraseFromParent();
10531 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10532 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10533 Register Result =
MI.getOperand(0).getReg();
10534 LLT OrigTy = MRI.getType(Result);
10538 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10539 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10541 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10543 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10544 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10547 MI.eraseFromParent();
10553 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10558 MI.eraseFromParent();
10563 MI.eraseFromParent();
10570 unsigned BitSize = SrcTy.getScalarSizeInBits();
10574 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10581 APInt ExpMask = Inf;
10583 APInt QNaNBitMask =
10587 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10588 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10589 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10590 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10591 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10593 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10597 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10599 LLT DstTyCopy = DstTy;
10601 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10629 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10632 Mask &= ~PartialCheck;
10641 else if (PartialCheck ==
fcZero)
10653 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10654 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10655 auto SubnormalRes =
10657 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10659 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10660 appendToRes(SubnormalRes);
10667 else if (PartialCheck ==
fcInf)
10672 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10679 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10680 if (PartialCheck ==
fcNan) {
10684 }
else if (PartialCheck ==
fcQNan) {
10694 Abs, InfWithQnanBitC);
10695 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10702 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10704 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10705 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10708 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10710 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10713 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10714 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10716 appendToRes(NormalRes);
10720 MI.eraseFromParent();
10726 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10727 MI.getFirst4RegLLTs();
10736 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10737 Op1Ty = MRI.getType(Op1Reg);
10738 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10739 Op2Ty = MRI.getType(Op2Reg);
10743 if (MaskTy.isScalar()) {
10751 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10754 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10756 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10758 if (DstTy.isVector()) {
10760 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10761 MaskReg = ShufSplat.getReg(0);
10765 }
else if (!DstTy.isVector()) {
10770 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10774 if (!Op1Ty.getScalarType().isAnyScalar() &&
10775 !Op1Ty.getScalarType().isInteger())
10776 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10778 if (!Op2Ty.getScalarType().isAnyScalar() &&
10779 !Op2Ty.getScalarType().isInteger()) {
10781 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10782 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10785 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10786 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10787 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10792 if (DstTy == Op1TyInt)
10795 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10799 MI.eraseFromParent();
10805 unsigned Opcode =
MI.getOpcode();
10808 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10809 : TargetOpcode::G_UDIV,
10810 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10812 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10813 : TargetOpcode::G_UREM,
10814 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10815 MI.eraseFromParent();
10825 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10829 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10832 MI.eraseFromParent();
10842 Register SrcReg =
MI.getOperand(1).getReg();
10843 LLT Ty = MRI.getType(SrcReg);
10844 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10847 MI.eraseFromParent();
10853 Register SrcReg =
MI.getOperand(1).getReg();
10854 Register DestReg =
MI.getOperand(0).getReg();
10856 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10857 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10860 MI.eraseFromParent();
10866 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10867 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10868 "Expected G_ABDS or G_ABDU instruction");
10870 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10871 LLT Ty = MRI.getType(LHS);
10881 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10883 MI.eraseFromParent();
10889 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10890 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10891 "Expected G_ABDS or G_ABDU instruction");
10893 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10894 LLT Ty = MRI.getType(LHS);
10899 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10900 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10901 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10903 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10904 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10906 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10908 MI.eraseFromParent();
10913 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10918 if (!(SrcTy.getScalarType().isAnyScalar() ||
10919 SrcTy.getScalarType().isInteger())) {
10921 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10922 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10925 if (MRI.getType(DstReg) != TyInt) {
10929 .buildAnd(TyInt, CastedSrc,
10932 DstTy.getScalarSizeInBits())))
10944 MI.eraseFromParent();
10950 Register SrcReg =
MI.getOperand(1).getReg();
10951 LLT SrcTy = MRI.getType(SrcReg);
10952 LLT DstTy = MRI.getType(SrcReg);
10955 if (SrcTy.isScalar()) {
10960 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10971 Register ListPtr =
MI.getOperand(1).getReg();
10972 LLT PtrTy = MRI.getType(ListPtr);
10979 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10981 const Align A(
MI.getOperand(2).getImm());
10983 if (
A > TLI.getMinStackArgumentAlignment()) {
10985 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10986 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10987 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10988 VAList = AndDst.getReg(0);
10995 LLT LLTTy = MRI.getType(Dst);
10998 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10999 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
11004 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
11006 Align EltAlignment =
DL.getABITypeAlign(Ty);
11009 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
11011 MI.eraseFromParent();
11016 unsigned OpCode =
MI.getOpcode();
11017 assert((OpCode == TargetOpcode::G_SMULFIX ||
11018 OpCode == TargetOpcode::G_UMULFIX ||
11019 OpCode == TargetOpcode::G_SMULFIXSAT ||
11020 OpCode == TargetOpcode::G_UMULFIXSAT) &&
11021 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
11022 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
11023 LLT Ty = MRI.getType(Dst);
11024 unsigned Scale =
MI.getOperand(3).getImm();
11026 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
11027 OpCode == TargetOpcode::G_UMULFIXSAT);
11028 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
11029 OpCode == TargetOpcode::G_SMULFIXSAT);
11031 if (!Saturating && Scale == 0) {
11033 MI.eraseFromParent();
11039 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
11062 MI.eraseFromParent();
11069 unsigned NumBits = Ty.getScalarSizeInBits();
11071 if (!Ty.isVector() && ValVRegAndVal) {
11072 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
11080 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11103 auto &MF = *
MI.getParent()->getParent();
11108 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11109 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11112 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11113 const auto &DstMMO = **
MI.memoperands_begin();
11115 if (DstAlignCanChange) {
11118 Align NewAlign =
DL.getABITypeAlign(IRTy);
11119 if (NewAlign > Alignment) {
11128 MachineIRBuilder MIB(
MI);
11130 LLT LargestTy = MemOps[0];
11131 for (
unsigned i = 1; i < MemOps.
size(); i++)
11133 LargestTy = MemOps[i];
11145 LLT PtrTy = MRI.getType(Dst);
11146 unsigned DstOff = 0;
11147 unsigned Size = KnownLen;
11148 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11149 LLT Ty = MemOps[
I];
11152 if (TySize >
Size) {
11156 DstOff -= TySize -
Size;
11166 TLI.isTruncateFree(LargestVT, VT))
11167 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11180 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11183 MIB.buildStore(
Value, Ptr, *StoreMMO);
11188 MI.eraseFromParent();
11196 auto &MF = *
MI.getParent()->getParent();
11200 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11201 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11204 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11210 const auto &DstMMO = **
MI.memoperands_begin();
11211 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11213 if (DstAlignCanChange) {
11216 Align NewAlign =
DL.getABITypeAlign(IRTy);
11221 if (!
TRI->hasStackRealignment(MF))
11222 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11223 NewAlign = std::min(NewAlign, *StackAlign);
11225 if (NewAlign > Alignment) {
11234 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11236 MachineIRBuilder MIB(
MI);
11242 LLT SrcTy = MRI.getType(Src);
11243 LLT DstTy = MRI.getType(Dst);
11246 unsigned CurrOffset = 0;
11247 unsigned Size = KnownLen;
11248 for (
auto CopyTy : MemOps) {
11249 TypeSize TySize = CopyTy.getSizeInBytes();
11253 if (TySize >
Size) {
11254 unsigned Overlap = TySize -
Size;
11255 assert(Overlap < CurrOffset &&
11256 "overlapping memcpy load/store spans the whole region or more");
11257 CurrOffset -= Overlap;
11267 if (CurrOffset != 0) {
11269 MIB.buildConstant(
LLT::integer(SrcIndexSize), CurrOffset).getReg(0);
11270 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11272 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11276 if (CurrOffset != 0) {
11277 if (SrcIndexSize != DstIndexSize) {
11279 MIB.buildConstant(
LLT::integer(DstIndexSize), CurrOffset).getReg(0);
11281 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11283 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11284 CurrOffset += TySize;
11288 MI.eraseFromParent();
11296 auto &MF = *
MI.getParent()->getParent();
11300 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11301 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11304 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11305 const auto &DstMMO = **
MI.memoperands_begin();
11306 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11308 if (DstAlignCanChange) {
11311 Align NewAlign =
DL.getABITypeAlign(IRTy);
11316 if (!
TRI->hasStackRealignment(MF))
11317 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11318 NewAlign = std::min(NewAlign, *StackAlign);
11320 if (NewAlign > Alignment) {
11329 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11331 MachineIRBuilder MIB(
MI);
11335 unsigned CurrOffset = 0;
11336 unsigned Size = KnownLen;
11337 SmallVector<Register, 16> LoadVals;
11338 for (
auto CopyTy : MemOps) {
11339 TypeSize TySize = CopyTy.getSizeInBytes();
11343 if (TySize >
Size) {
11344 unsigned Overlap = TySize -
Size;
11345 assert(Overlap < CurrOffset &&
11346 "overlapping memmove load spans the whole region or more");
11347 CurrOffset -= Overlap;
11355 if (CurrOffset != 0) {
11356 LLT SrcTy = MRI.getType(Src);
11359 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11361 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11362 CurrOffset += TySize;
11368 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11369 LLT CopyTy = MemOps[
I];
11374 if (TySize >
Size) {
11375 unsigned Overlap = TySize -
Size;
11376 assert(Overlap < CurrOffset &&
11377 "overlapping memmove store spans the whole region or more");
11378 CurrOffset -= Overlap;
11385 if (CurrOffset != 0) {
11386 LLT DstTy = MRI.getType(Dst);
11389 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11391 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11392 CurrOffset += TySize;
11395 MI.eraseFromParent();
11402 const unsigned Opc =
MI.getOpcode();
11403 assert((
Opc == TargetOpcode::G_MEMCPY ||
11404 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11405 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11406 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11407 "Expected memcpy like instruction");
11409 if (KnownLen == 0) {
11410 MI.eraseFromParent();
11414 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11415 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11418 if (
Opc == TargetOpcode::G_MEMMOVE)
11419 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11421 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11422 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11432 bool DstAlignCanChange;
11433 std::vector<LLT> MemOps;
11435 DstAlignCanChange, MemOps))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static bool 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 bool supportSwiftError() const
Return true if the target supports swifterror attribute.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Type * getType() const
All values are typed, get the type of this value.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
ImplicitDefMatch m_GImplicitDef()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(Register Def, const MachineRegisterInfo &MRI)
Determines if Def defines a constant integer or a splat vector of constant integers.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, llvm::function_ref< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
LLVM_ABI bool canLowerMemCpyFamily(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned MaxLen, Register &Dst, Register &Src, uint64_t &KnownLen, Align &Alignment, bool &DstAlignCanChange, std::vector< LLT > &MemOps)
Matcher for memcpy-like instructions.
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
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.