44#define DEBUG_TYPE "legalizer"
57 auto InsertPt =
MBB.getFirstTerminatorForward();
59 if (InsertPt ==
MBB.end() ||
60 InsertPt->getOpcode() != TargetOpcode::G_INVOKE_REGION_START)
64 if (Def->getParent() == &
MBB)
65 for (
auto I = InsertPt,
E =
MBB.end();
I !=
E; ++
I)
78static std::pair<int, int>
88 if (LeftoverSize == 0)
93 if (LeftoverSize % EltSize != 0)
102 return std::make_pair(
NumParts, NumLeftover);
110 switch (Ty.getSizeInBits()) {
151 auto Step = LI.getAction(
MI, MRI);
152 switch (Step.Action) {
167 return bitcast(
MI, Step.TypeIdx, Step.NewType);
170 return lower(
MI, Step.TypeIdx, Step.NewType);
179 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
187void LegalizerHelper::insertParts(
Register DstReg,
209 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
211 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
212 return mergeMixedSubvectors(DstReg, AllRegs);
218 extractGCDType(GCDRegs, GCDTy, PartReg);
219 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
220 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
225 LLT Ty = MRI.getType(
Reg);
233void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
236 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
237 appendVectorElts(AllElts, PartRegs[i]);
240 if (!MRI.getType(Leftover).isVector())
243 appendVectorElts(AllElts, Leftover);
245 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
251 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
253 const int StartIdx = Regs.
size();
254 const int NumResults =
MI.getNumOperands() - 1;
256 for (
int I = 0;
I != NumResults; ++
I)
257 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
262 LLT SrcTy = MRI.getType(SrcReg);
263 if (SrcTy == GCDTy) {
269 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
276 LLT SrcTy = MRI.getType(SrcReg);
278 extractGCDType(Parts, GCDTy, SrcReg);
282LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
284 unsigned PadStrategy) {
289 int NumOrigSrc = VRegs.
size();
295 if (NumOrigSrc <
NumParts * NumSubParts) {
296 if (PadStrategy == TargetOpcode::G_ZEXT)
297 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
298 else if (PadStrategy == TargetOpcode::G_ANYEXT)
299 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
301 assert(PadStrategy == TargetOpcode::G_SEXT);
306 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
323 bool AllMergePartsArePadding =
true;
326 for (
int J = 0; J != NumSubParts; ++J) {
327 int Idx =
I * NumSubParts + J;
328 if (Idx >= NumOrigSrc) {
329 SubMerge[J] = PadReg;
333 SubMerge[J] = VRegs[
Idx];
336 AllMergePartsArePadding =
false;
342 if (AllMergePartsArePadding && !AllPadReg) {
343 if (PadStrategy == TargetOpcode::G_ANYEXT)
344 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
345 else if (PadStrategy == TargetOpcode::G_ZEXT)
346 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
355 Remerge[
I] = AllPadReg;
359 if (NumSubParts == 1)
360 Remerge[
I] = SubMerge[0];
362 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
365 if (AllMergePartsArePadding && !AllPadReg)
366 AllPadReg = Remerge[
I];
369 VRegs = std::move(Remerge);
373void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
375 LLT DstTy = MRI.getType(DstReg);
380 if (DstTy == LCMTy) {
381 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
385 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
394 UnmergeDefs[0] = DstReg;
395 for (
unsigned I = 1;
I != NumDefs; ++
I)
396 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
399 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
407#define RTLIBCASE_INT(LibcallPrefix) \
411 return RTLIB::LibcallPrefix##32; \
413 return RTLIB::LibcallPrefix##64; \
415 return RTLIB::LibcallPrefix##128; \
417 llvm_unreachable("unexpected size"); \
421#define RTLIBCASE(LibcallPrefix) \
425 return RTLIB::LibcallPrefix##32; \
427 return RTLIB::LibcallPrefix##64; \
429 return RTLIB::LibcallPrefix##80; \
431 return RTLIB::LibcallPrefix##128; \
433 llvm_unreachable("unexpected size"); \
438 case TargetOpcode::G_LROUND:
440 case TargetOpcode::G_LLROUND:
442 case TargetOpcode::G_MUL:
444 case TargetOpcode::G_SDIV:
446 case TargetOpcode::G_UDIV:
448 case TargetOpcode::G_SREM:
450 case TargetOpcode::G_UREM:
452 case TargetOpcode::G_CTLZ_ZERO_POISON:
454 case TargetOpcode::G_FADD:
456 case TargetOpcode::G_FSUB:
458 case TargetOpcode::G_FMUL:
460 case TargetOpcode::G_FDIV:
462 case TargetOpcode::G_FEXP:
464 case TargetOpcode::G_FEXP2:
466 case TargetOpcode::G_FEXP10:
468 case TargetOpcode::G_FREM:
470 case TargetOpcode::G_FPOW:
472 case TargetOpcode::G_FPOWI:
474 case TargetOpcode::G_FMA:
476 case TargetOpcode::G_FSIN:
478 case TargetOpcode::G_FCOS:
480 case TargetOpcode::G_FTAN:
482 case TargetOpcode::G_FASIN:
484 case TargetOpcode::G_FACOS:
486 case TargetOpcode::G_FATAN:
488 case TargetOpcode::G_FATAN2:
490 case TargetOpcode::G_FSINH:
492 case TargetOpcode::G_FCOSH:
494 case TargetOpcode::G_FTANH:
496 case TargetOpcode::G_FSINCOS:
498 case TargetOpcode::G_FMODF:
500 case TargetOpcode::G_FLOG10:
502 case TargetOpcode::G_FLOG:
504 case TargetOpcode::G_FLOG2:
506 case TargetOpcode::G_FLDEXP:
508 case TargetOpcode::G_FCEIL:
510 case TargetOpcode::G_FFLOOR:
512 case TargetOpcode::G_FMINNUM:
514 case TargetOpcode::G_FMAXNUM:
516 case TargetOpcode::G_FMINIMUMNUM:
518 case TargetOpcode::G_FMAXIMUMNUM:
520 case TargetOpcode::G_FSQRT:
522 case TargetOpcode::G_FRINT:
524 case TargetOpcode::G_FNEARBYINT:
526 case TargetOpcode::G_INTRINSIC_TRUNC:
528 case TargetOpcode::G_INTRINSIC_ROUND:
530 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
532 case TargetOpcode::G_INTRINSIC_LRINT:
534 case TargetOpcode::G_INTRINSIC_LLRINT:
544 return TLI.supportSwiftError() &&
546 Attribute::SwiftError);
562 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
563 .removeAttribute(Attribute::NoAlias)
564 .removeAttribute(Attribute::NonNull)
569 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
570 CallerAttrs.hasRetAttr(Attribute::SExt))
574 if (
F.getFnAttribute(
"disable-tail-calls").getValueAsBool())
585 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
592 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
600 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
603 if (Ret->getNumImplicitOperands() != 1)
606 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
623 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
628 Info.OrigRet = Result;
631 (Result.Ty->isVoidTy() ||
632 Result.Ty ==
MIRBuilder.getMF().getFunction().getReturnType()) &&
643 if (
MI && Info.LoweredTailCall) {
644 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
654 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
655 "Expected instr following MI to be return or debug inst?");
658 Next->eraseFromParent();
659 }
while (
MI->getNextNode());
674 RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(
Libcall);
675 if (LibcallImpl == RTLIB::Unsupported)
693 Args.push_back({MO.getReg(), OpType, 0});
707 LLT DstTy =
MRI.getType(DstSin);
712 unsigned AddrSpace =
DL.getAllocaAddrSpace();
730 if (LibcallResult != LegalizeResult::Legalized)
738 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
739 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
740 MI.eraseFromParent();
755 LLT DstTy = MRI.getType(DstFrac);
760 unsigned AddrSpace =
DL.getAllocaAddrSpace();
761 MachinePointerInfo PtrInfo;
770 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
773 if (LibcallResult != LegalizeResult::Legalized)
779 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
780 MI.eraseFromParent();
791 case TargetOpcode::G_FPEXT:
793 case TargetOpcode::G_FPTRUNC:
795 case TargetOpcode::G_FPTOSI:
797 case TargetOpcode::G_FPTOUI:
799 case TargetOpcode::G_SITOFP:
801 case TargetOpcode::G_UITOFP:
811 if (FromType->isIntegerTy()) {
812 if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
813 Arg.
Flags[0].setSExt();
815 Arg.
Flags[0].setZExt();
826 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
830 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
834 LLT OpLLT = MRI.getType(Reg);
840 Args.push_back({Reg,
OpTy, 0});
843 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
844 RTLIB::Libcall RTLibcall;
845 unsigned Opc =
MI.getOpcode();
847 case TargetOpcode::G_BZERO:
848 RTLibcall = RTLIB::BZERO;
850 case TargetOpcode::G_MEMCPY:
851 RTLibcall = RTLIB::MEMCPY;
852 Args[0].Flags[0].setReturned();
854 case TargetOpcode::G_MEMMOVE:
855 RTLibcall = RTLIB::MEMMOVE;
856 Args[0].Flags[0].setReturned();
858 case TargetOpcode::G_MEMSET:
859 RTLibcall = RTLIB::MEMSET;
860 Args[0].Flags[0].setReturned();
869 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
872 if (RTLibcallImpl == RTLIB::Unsupported) {
879 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
886 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
896 if (Info.LoweredTailCall) {
897 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
907 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
908 "Expected instr following MI to be return or debug inst?");
911 Next->eraseFromParent();
912 }
while (
MI.getNextNode());
922 unsigned Opc =
MI.getOpcode();
924 auto &MMO = AtomicMI.getMMO();
925 auto Ordering = MMO.getMergedOrdering();
926 LLT MemType = MMO.getMemoryType();
929 return RTLIB::UNKNOWN_LIBCALL;
931#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
933 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
935 case TargetOpcode::G_ATOMIC_CMPXCHG:
936 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
937 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
938 return getOutlineAtomicHelper(LC, Ordering, MemSize);
940 case TargetOpcode::G_ATOMICRMW_XCHG: {
941 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
942 return getOutlineAtomicHelper(LC, Ordering, MemSize);
944 case TargetOpcode::G_ATOMICRMW_ADD:
945 case TargetOpcode::G_ATOMICRMW_SUB: {
946 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
947 return getOutlineAtomicHelper(LC, Ordering, MemSize);
949 case TargetOpcode::G_ATOMICRMW_AND: {
950 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
951 return getOutlineAtomicHelper(LC, Ordering, MemSize);
953 case TargetOpcode::G_ATOMICRMW_OR: {
954 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
955 return getOutlineAtomicHelper(LC, Ordering, MemSize);
957 case TargetOpcode::G_ATOMICRMW_XOR: {
958 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
959 return getOutlineAtomicHelper(LC, Ordering, MemSize);
962 return RTLIB::UNKNOWN_LIBCALL;
975 unsigned Opc =
MI.getOpcode();
977 case TargetOpcode::G_ATOMIC_CMPXCHG:
978 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
981 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
982 MI.getFirst4RegLLTs();
985 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
986 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
987 NewLLT) =
MI.getFirst5RegLLTs();
997 case TargetOpcode::G_ATOMICRMW_XCHG:
998 case TargetOpcode::G_ATOMICRMW_ADD:
999 case TargetOpcode::G_ATOMICRMW_SUB:
1000 case TargetOpcode::G_ATOMICRMW_AND:
1001 case TargetOpcode::G_ATOMICRMW_OR:
1002 case TargetOpcode::G_ATOMICRMW_XOR: {
1003 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
1006 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
1010 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
1025 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
1027 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
1030 if (RTLibcallImpl == RTLIB::Unsupported) {
1037 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
1051static RTLIB::Libcall
1053 RTLIB::Libcall RTLibcall;
1054 switch (
MI.getOpcode()) {
1055 case TargetOpcode::G_GET_FPENV:
1056 RTLibcall = RTLIB::FEGETENV;
1058 case TargetOpcode::G_SET_FPENV:
1059 case TargetOpcode::G_RESET_FPENV:
1060 RTLibcall = RTLIB::FESETENV;
1062 case TargetOpcode::G_GET_FPMODE:
1063 RTLibcall = RTLIB::FEGETMODE;
1065 case TargetOpcode::G_SET_FPMODE:
1066 case TargetOpcode::G_RESET_FPMODE:
1067 RTLibcall = RTLIB::FESETMODE;
1099 LLT StateTy = MRI.getType(Dst);
1102 MachinePointerInfo TempPtrInfo;
1106 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1111 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
1119 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1137 LLT StateTy = MRI.getType(Src);
1140 MachinePointerInfo TempPtrInfo;
1149 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1154 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1155 LocObserver,
nullptr);
1161static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1163#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1167 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1169 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1171 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1173 llvm_unreachable("unexpected size"); \
1206 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1209 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1216 LLT DstTy = MRI.getType(DstReg);
1217 const auto Cond =
Cmp->getCond();
1218 Type *RetTy = TLI.getCmpLibcallReturnType(Ctx);
1223 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1228 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1232 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1239 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1245 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1247 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1260 const auto [OeqLibcall, OeqPred] =
1262 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1264 const auto [UnoLibcall, UnoPred] =
1266 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1281 const auto [OeqLibcall, OeqPred] =
1286 const auto [UnoLibcall, UnoPred] =
1291 if (NotOeq && NotUno)
1310 const auto [InversedLibcall, InversedPred] =
1312 if (!BuildLibcall(InversedLibcall,
1337 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1339 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1342 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1348 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1353 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1355 switch (
MI.getOpcode()) {
1358 case TargetOpcode::G_MUL:
1359 case TargetOpcode::G_SDIV:
1360 case TargetOpcode::G_UDIV:
1361 case TargetOpcode::G_SREM:
1362 case TargetOpcode::G_UREM:
1363 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1364 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1372 case TargetOpcode::G_FADD:
1373 case TargetOpcode::G_FSUB:
1374 case TargetOpcode::G_FMUL:
1375 case TargetOpcode::G_FDIV:
1376 case TargetOpcode::G_FMA:
1377 case TargetOpcode::G_FPOW:
1378 case TargetOpcode::G_FREM:
1379 case TargetOpcode::G_FCOS:
1380 case TargetOpcode::G_FSIN:
1381 case TargetOpcode::G_FTAN:
1382 case TargetOpcode::G_FACOS:
1383 case TargetOpcode::G_FASIN:
1384 case TargetOpcode::G_FATAN:
1385 case TargetOpcode::G_FATAN2:
1386 case TargetOpcode::G_FCOSH:
1387 case TargetOpcode::G_FSINH:
1388 case TargetOpcode::G_FTANH:
1389 case TargetOpcode::G_FLOG10:
1390 case TargetOpcode::G_FLOG:
1391 case TargetOpcode::G_FLOG2:
1392 case TargetOpcode::G_FEXP:
1393 case TargetOpcode::G_FEXP2:
1394 case TargetOpcode::G_FEXP10:
1395 case TargetOpcode::G_FCEIL:
1396 case TargetOpcode::G_FFLOOR:
1397 case TargetOpcode::G_FMINNUM:
1398 case TargetOpcode::G_FMAXNUM:
1399 case TargetOpcode::G_FMINIMUMNUM:
1400 case TargetOpcode::G_FMAXIMUMNUM:
1401 case TargetOpcode::G_FSQRT:
1402 case TargetOpcode::G_FRINT:
1403 case TargetOpcode::G_FNEARBYINT:
1404 case TargetOpcode::G_INTRINSIC_TRUNC:
1405 case TargetOpcode::G_INTRINSIC_ROUND:
1406 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1407 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1411 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1419 case TargetOpcode::G_FSINCOS: {
1420 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1424 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1429 case TargetOpcode::G_FMODF: {
1430 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1434 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1439 case TargetOpcode::G_LROUND:
1440 case TargetOpcode::G_LLROUND:
1441 case TargetOpcode::G_INTRINSIC_LRINT:
1442 case TargetOpcode::G_INTRINSIC_LLRINT: {
1443 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1447 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1449 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1455 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1458 MI.eraseFromParent();
1461 case TargetOpcode::G_FPOWI:
1462 case TargetOpcode::G_FLDEXP: {
1463 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1467 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1469 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1474 {
MI.getOperand(1).getReg(), HLTy, 0},
1475 {
MI.getOperand(2).getReg(), ITy, 1}};
1476 Args[1].Flags[0].setSExt();
1478 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1483 case TargetOpcode::G_FPEXT:
1484 case TargetOpcode::G_FPTRUNC: {
1487 if (!FromTy || !ToTy)
1494 case TargetOpcode::G_FCMP: {
1498 MI.eraseFromParent();
1501 case TargetOpcode::G_FPTOSI:
1502 case TargetOpcode::G_FPTOUI: {
1506 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1507 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1510 FromTy, LocObserver);
1515 case TargetOpcode::G_SITOFP:
1516 case TargetOpcode::G_UITOFP: {
1517 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1520 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1522 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1529 case TargetOpcode::G_ATOMICRMW_XCHG:
1530 case TargetOpcode::G_ATOMICRMW_ADD:
1531 case TargetOpcode::G_ATOMICRMW_SUB:
1532 case TargetOpcode::G_ATOMICRMW_AND:
1533 case TargetOpcode::G_ATOMICRMW_OR:
1534 case TargetOpcode::G_ATOMICRMW_XOR:
1535 case TargetOpcode::G_ATOMIC_CMPXCHG:
1536 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1542 case TargetOpcode::G_BZERO:
1543 case TargetOpcode::G_MEMCPY:
1544 case TargetOpcode::G_MEMMOVE:
1545 case TargetOpcode::G_MEMSET: {
1550 MI.eraseFromParent();
1553 case TargetOpcode::G_GET_FPENV:
1554 case TargetOpcode::G_GET_FPMODE: {
1560 case TargetOpcode::G_SET_FPENV:
1561 case TargetOpcode::G_SET_FPMODE: {
1567 case TargetOpcode::G_RESET_FPENV:
1568 case TargetOpcode::G_RESET_FPMODE: {
1576 MI.eraseFromParent();
1583 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1586 switch (
MI.getOpcode()) {
1589 case TargetOpcode::G_IMPLICIT_DEF: {
1591 LLT DstTy = MRI.getType(DstReg);
1599 if (SizeOp0 % NarrowSize != 0) {
1604 MI.eraseFromParent();
1608 int NumParts = SizeOp0 / NarrowSize;
1615 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1617 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1618 MI.eraseFromParent();
1621 case TargetOpcode::G_CONSTANT: {
1622 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1623 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1624 unsigned TotalSize = Ty.getSizeInBits();
1626 int NumParts = TotalSize / NarrowSize;
1630 unsigned Offset =
I * NarrowSize;
1637 unsigned LeftoverBits = TotalSize -
NumParts * NarrowSize;
1639 if (LeftoverBits != 0) {
1647 insertParts(
MI.getOperand(0).getReg(),
1648 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1650 MI.eraseFromParent();
1653 case TargetOpcode::G_SEXT:
1654 case TargetOpcode::G_ZEXT:
1655 case TargetOpcode::G_ANYEXT:
1657 case TargetOpcode::G_TRUNC: {
1661 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1663 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1667 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1668 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1669 MI.eraseFromParent();
1672 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1673 case TargetOpcode::G_FREEZE: {
1677 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1682 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1684 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1686 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1690 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1691 MI.eraseFromParent();
1694 case TargetOpcode::G_ADD:
1695 case TargetOpcode::G_SUB:
1696 case TargetOpcode::G_SADDO:
1697 case TargetOpcode::G_SSUBO:
1698 case TargetOpcode::G_SADDE:
1699 case TargetOpcode::G_SSUBE:
1700 case TargetOpcode::G_UADDO:
1701 case TargetOpcode::G_USUBO:
1702 case TargetOpcode::G_UADDE:
1703 case TargetOpcode::G_USUBE:
1705 case TargetOpcode::G_MUL:
1706 case TargetOpcode::G_UMULH:
1707 case TargetOpcode::G_SMULH:
1709 case TargetOpcode::G_EXTRACT:
1711 case TargetOpcode::G_INSERT:
1713 case TargetOpcode::G_LOAD: {
1715 Register DstReg = LoadMI.getDstReg();
1716 LLT DstTy = MRI.getType(DstReg);
1720 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1721 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1722 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1724 LoadMI.eraseFromParent();
1730 case TargetOpcode::G_ZEXTLOAD:
1731 case TargetOpcode::G_SEXTLOAD:
1732 case TargetOpcode::G_FPEXTLOAD: {
1734 Register DstReg = LoadMI.getDstReg();
1735 Register PtrReg = LoadMI.getPointerReg();
1737 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1738 auto &MMO = LoadMI.getMMO();
1741 if (MemSize == NarrowSize) {
1743 }
else if (MemSize < NarrowSize) {
1744 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1745 }
else if (MemSize > NarrowSize) {
1757 LoadMI.eraseFromParent();
1760 case TargetOpcode::G_STORE: {
1763 Register SrcReg = StoreMI.getValueReg();
1764 LLT SrcTy = MRI.getType(SrcReg);
1765 if (SrcTy.isVector())
1768 int NumParts = SizeOp0 / NarrowSize;
1770 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1771 if (SrcTy.isVector() && LeftoverBits != 0)
1774 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1775 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1777 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1778 StoreMI.eraseFromParent();
1784 case TargetOpcode::G_FPTRUNCSTORE: {
1786 Register SrcReg = StoreMI.getValueReg();
1787 Register PtrReg = StoreMI.getPointerReg();
1789 auto &MMO = StoreMI.getMMO();
1791 if (MemSize > NarrowSize) {
1795 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1796 if (MemSize == NarrowSize) {
1798 }
else if (MemSize < NarrowSize) {
1799 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1803 StoreMI.eraseFromParent();
1806 case TargetOpcode::G_SELECT:
1808 case TargetOpcode::G_AND:
1809 case TargetOpcode::G_OR:
1810 case TargetOpcode::G_XOR: {
1822 case TargetOpcode::G_SHL:
1823 case TargetOpcode::G_LSHR:
1824 case TargetOpcode::G_ASHR:
1826 case TargetOpcode::G_CTLZ:
1827 case TargetOpcode::G_CTLZ_ZERO_POISON:
1828 case TargetOpcode::G_CTTZ:
1829 case TargetOpcode::G_CTTZ_ZERO_POISON:
1830 case TargetOpcode::G_CTLS:
1831 case TargetOpcode::G_CTPOP:
1833 switch (
MI.getOpcode()) {
1834 case TargetOpcode::G_CTLZ:
1835 case TargetOpcode::G_CTLZ_ZERO_POISON:
1837 case TargetOpcode::G_CTTZ:
1838 case TargetOpcode::G_CTTZ_ZERO_POISON:
1840 case TargetOpcode::G_CTPOP:
1842 case TargetOpcode::G_CTLS:
1852 case TargetOpcode::G_INTTOPTR:
1860 case TargetOpcode::G_PTRTOINT:
1868 case TargetOpcode::G_PHI: {
1871 if (SizeOp0 % NarrowSize != 0)
1874 unsigned NumParts = SizeOp0 / NarrowSize;
1878 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1881 OpMBB,
MI.getOperand(i).getReg(), MRI));
1887 for (
unsigned i = 0; i <
NumParts; ++i) {
1888 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1890 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1891 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1892 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1895 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1897 MI.eraseFromParent();
1900 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1901 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1905 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1911 case TargetOpcode::G_ICMP: {
1913 LLT SrcTy = MRI.getType(LHS);
1919 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1925 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1926 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1932 LLT ResTy = MRI.getType(Dst);
1939 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1940 auto LHS = std::get<0>(LHSAndRHS);
1941 auto RHS = std::get<1>(LHSAndRHS);
1942 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1949 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1950 auto LHS = std::get<0>(LHSAndRHS);
1951 auto RHS = std::get<1>(LHSAndRHS);
1952 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1953 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1954 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1955 TargetOpcode::G_ZEXT);
1962 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1963 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1964 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1969 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1973 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1978 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1982 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1985 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1988 LHSPartRegs[
I], RHSPartRegs[
I]);
1989 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1995 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
2004 CmpOut = MRI.createGenericVirtualRegister(ResTy);
2008 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
2009 RHSLeftoverRegs[
I]);
2011 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
2012 RHSLeftoverRegs[
I]);
2015 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
2016 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
2022 MI.eraseFromParent();
2025 case TargetOpcode::G_FCMP:
2034 case TargetOpcode::G_SEXT_INREG: {
2038 int64_t SizeInBits =
MI.getOperand(2).getImm();
2047 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2048 MO1.
setReg(TruncMIB.getReg(0));
2051 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2063 if (SizeOp0 % NarrowSize != 0)
2065 int NumParts = SizeOp0 / NarrowSize;
2073 for (
int i = 0; i <
NumParts; ++i) {
2074 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2089 for (
int i = 0; i <
NumParts; ++i) {
2092 PartialExtensionReg = DstRegs.
back();
2094 assert(PartialExtensionReg &&
2095 "Expected to visit partial extension before full");
2096 if (FullExtensionReg) {
2101 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2103 FullExtensionReg = DstRegs.
back();
2108 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2111 PartialExtensionReg = DstRegs.
back();
2117 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2118 MI.eraseFromParent();
2121 case TargetOpcode::G_BSWAP:
2122 case TargetOpcode::G_BITREVERSE: {
2123 if (SizeOp0 % NarrowSize != 0)
2128 unsigned NumParts = SizeOp0 / NarrowSize;
2132 for (
unsigned i = 0; i <
NumParts; ++i) {
2133 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2134 {SrcRegs[NumParts - 1 - i]});
2138 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2141 MI.eraseFromParent();
2144 case TargetOpcode::G_PTR_ADD:
2145 case TargetOpcode::G_PTRMASK: {
2153 case TargetOpcode::G_FPTOUI:
2154 case TargetOpcode::G_FPTOSI:
2155 case TargetOpcode::G_FPTOUI_SAT:
2156 case TargetOpcode::G_FPTOSI_SAT:
2158 case TargetOpcode::G_FPEXT:
2165 case TargetOpcode::G_FLDEXP:
2166 case TargetOpcode::G_STRICT_FLDEXP:
2168 case TargetOpcode::G_VSCALE: {
2170 LLT Ty = MRI.getType(Dst);
2174 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2175 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2176 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2179 MI.eraseFromParent();
2186 LLT Ty = MRI.getType(Val);
2187 if (Ty.isScalar() && !Ty.isFloat())
2194 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2196 if (Ty.isPointer()) {
2197 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2199 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2205 if (Ty.isPointerVector())
2206 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2207 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2211 unsigned OpIdx,
unsigned ExtOpcode) {
2213 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2214 MO.
setReg(ExtB.getReg(0));
2220 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2222 MO.
setReg(ExtB.getReg(0));
2228 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2229 MO.
setReg(ExtB.getReg(0));
2233 unsigned OpIdx,
unsigned TruncOpcode) {
2235 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2237 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2244 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2246 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2251 unsigned OpIdx,
unsigned ExtOpcode) {
2253 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2255 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2264 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2266 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2272 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2282 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2289LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2294 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2295 if (DstTy.isVector())
2298 LLT SrcTy =
MRI.getType(Src1Reg);
2299 const int DstSize = DstTy.getSizeInBits();
2300 const int SrcSize = SrcTy.getSizeInBits();
2302 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2304 unsigned NumOps =
MI.getNumOperands();
2305 unsigned NumSrc =
MI.getNumOperands() - 1;
2306 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2308 if (WideSize >= DstSize) {
2312 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2313 const unsigned Offset = (
I - 1) * PartSize;
2321 MRI.createGenericVirtualRegister(WideTy);
2326 ResultReg = NextResult;
2329 if (WideSize > DstSize)
2331 else if (DstTy.isPointer())
2333 else if (DstTy != WideTy)
2336 MI.eraseFromParent();
2361 const int GCD = std::gcd(SrcSize, WideSize);
2371 if (GCD == SrcSize) {
2374 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2375 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2381 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2383 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2387 const int PartsPerGCD = WideSize / GCD;
2391 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2393 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2400 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2402 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2403 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2406 MI.eraseFromParent();
2411LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2416 int NumDst =
MI.getNumOperands() - 1;
2417 Register SrcReg =
MI.getOperand(NumDst).getReg();
2418 LLT SrcTy = MRI.getType(SrcReg);
2422 Register Dst0Reg =
MI.getOperand(0).getReg();
2423 LLT DstTy = MRI.getType(Dst0Reg);
2432 dbgs() <<
"Not casting non-integral address space integer\n");
2437 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2445 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2454 SrcTy = MRI.getType(SrcReg);
2458 for (
int I = 1;
I != NumDst; ++
I) {
2459 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2460 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2464 MI.eraseFromParent();
2475 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2479 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2482 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2500 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2505 if (PartsPerRemerge == 1) {
2508 for (
int I = 0;
I != NumUnmerge; ++
I) {
2509 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2511 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2512 int Idx =
I * PartsPerUnmerge + J;
2514 MIB.addDef(
MI.getOperand(Idx).getReg());
2517 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2521 MIB.addUse(Unmerge.getReg(
I));
2524 SmallVector<Register, 16> Parts;
2525 for (
int J = 0; J != NumUnmerge; ++J)
2526 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2529 for (
int I = 0;
I != NumDst; ++
I) {
2530 for (
int J = 0; J < PartsPerRemerge; ++J) {
2531 const int Idx =
I * PartsPerRemerge + J;
2535 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2536 RemergeParts.
clear();
2540 MI.eraseFromParent();
2545LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2547 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2548 unsigned Offset =
MI.getOperand(2).getImm();
2551 if (SrcTy.
isVector() || DstTy.isVector())
2563 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2567 if (DstTy.isPointer())
2574 MI.eraseFromParent();
2579 LLT ShiftTy = SrcTy;
2588 MI.eraseFromParent();
2619LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2621 if (TypeIdx != 0 || WideTy.
isVector())
2631LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2635 std::optional<Register> CarryIn;
2636 switch (
MI.getOpcode()) {
2639 case TargetOpcode::G_SADDO:
2640 Opcode = TargetOpcode::G_ADD;
2641 ExtOpcode = TargetOpcode::G_SEXT;
2643 case TargetOpcode::G_SSUBO:
2644 Opcode = TargetOpcode::G_SUB;
2645 ExtOpcode = TargetOpcode::G_SEXT;
2647 case TargetOpcode::G_UADDO:
2648 Opcode = TargetOpcode::G_ADD;
2649 ExtOpcode = TargetOpcode::G_ZEXT;
2651 case TargetOpcode::G_USUBO:
2652 Opcode = TargetOpcode::G_SUB;
2653 ExtOpcode = TargetOpcode::G_ZEXT;
2655 case TargetOpcode::G_SADDE:
2656 Opcode = TargetOpcode::G_UADDE;
2657 ExtOpcode = TargetOpcode::G_SEXT;
2658 CarryIn =
MI.getOperand(4).getReg();
2660 case TargetOpcode::G_SSUBE:
2661 Opcode = TargetOpcode::G_USUBE;
2662 ExtOpcode = TargetOpcode::G_SEXT;
2663 CarryIn =
MI.getOperand(4).getReg();
2665 case TargetOpcode::G_UADDE:
2666 Opcode = TargetOpcode::G_UADDE;
2667 ExtOpcode = TargetOpcode::G_ZEXT;
2668 CarryIn =
MI.getOperand(4).getReg();
2670 case TargetOpcode::G_USUBE:
2671 Opcode = TargetOpcode::G_USUBE;
2672 ExtOpcode = TargetOpcode::G_ZEXT;
2673 CarryIn =
MI.getOperand(4).getReg();
2689 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2690 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2694 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2696 .buildInstr(Opcode, {WideTy, CarryOutTy},
2697 {LHSExt, RHSExt, *CarryIn})
2700 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2702 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2703 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2704 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2709 MI.eraseFromParent();
2714LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2716 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2717 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2718 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2719 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2720 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2733 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2740 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2744 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2745 {ShiftL, ShiftR},
MI.getFlags());
2750 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2753 MI.eraseFromParent();
2758LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2767 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2769 LLT SrcTy = MRI.getType(
LHS);
2770 LLT OverflowTy = MRI.getType(OriginalOverflow);
2777 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2778 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2779 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2786 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2788 MachineInstrBuilder Mulo;
2789 if (WideMulCanOverflow)
2790 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2791 {LeftOperand, RightOperand});
2793 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2798 MachineInstrBuilder ExtResult;
2805 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2809 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2812 if (WideMulCanOverflow) {
2820 MI.eraseFromParent();
2826 unsigned Opcode =
MI.getOpcode();
2830 case TargetOpcode::G_ATOMICRMW_XCHG:
2831 case TargetOpcode::G_ATOMICRMW_ADD:
2832 case TargetOpcode::G_ATOMICRMW_SUB:
2833 case TargetOpcode::G_ATOMICRMW_AND:
2834 case TargetOpcode::G_ATOMICRMW_OR:
2835 case TargetOpcode::G_ATOMICRMW_XOR:
2836 case TargetOpcode::G_ATOMICRMW_MIN:
2837 case TargetOpcode::G_ATOMICRMW_MAX:
2838 case TargetOpcode::G_ATOMICRMW_UMIN:
2839 case TargetOpcode::G_ATOMICRMW_UMAX:
2840 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2846 case TargetOpcode::G_ATOMIC_CMPXCHG:
2847 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2854 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2864 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2869 case TargetOpcode::G_EXTRACT:
2870 return widenScalarExtract(
MI, TypeIdx, WideTy);
2871 case TargetOpcode::G_INSERT:
2872 return widenScalarInsert(
MI, TypeIdx, WideTy);
2873 case TargetOpcode::G_MERGE_VALUES:
2874 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2875 case TargetOpcode::G_UNMERGE_VALUES:
2876 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2877 case TargetOpcode::G_SADDO:
2878 case TargetOpcode::G_SSUBO:
2879 case TargetOpcode::G_UADDO:
2880 case TargetOpcode::G_USUBO:
2881 case TargetOpcode::G_SADDE:
2882 case TargetOpcode::G_SSUBE:
2883 case TargetOpcode::G_UADDE:
2884 case TargetOpcode::G_USUBE:
2885 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2886 case TargetOpcode::G_UMULO:
2887 case TargetOpcode::G_SMULO:
2888 return widenScalarMulo(
MI, TypeIdx, WideTy);
2889 case TargetOpcode::G_SADDSAT:
2890 case TargetOpcode::G_SSUBSAT:
2891 case TargetOpcode::G_SSHLSAT:
2892 case TargetOpcode::G_UADDSAT:
2893 case TargetOpcode::G_USUBSAT:
2894 case TargetOpcode::G_USHLSAT:
2895 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2896 case TargetOpcode::G_CTTZ:
2897 case TargetOpcode::G_CTTZ_ZERO_POISON:
2898 case TargetOpcode::G_CTLZ:
2899 case TargetOpcode::G_CTLZ_ZERO_POISON:
2900 case TargetOpcode::G_CTLS:
2901 case TargetOpcode::G_CTPOP: {
2914 case TargetOpcode::G_CTTZ:
2915 case TargetOpcode::G_CTTZ_ZERO_POISON:
2916 case TargetOpcode::G_CTLZ_ZERO_POISON:
2917 ExtOpc = TargetOpcode::G_ANYEXT;
2919 case TargetOpcode::G_CTLS:
2920 ExtOpc = TargetOpcode::G_SEXT;
2923 ExtOpc = TargetOpcode::G_ZEXT;
2926 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2927 LLT CurTy = MRI.getType(SrcReg);
2928 unsigned NewOpc = Opcode;
2929 if (NewOpc == TargetOpcode::G_CTTZ) {
2936 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2938 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2944 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2954 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2956 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2961 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2962 Opcode == TargetOpcode::G_CTLZ
2967 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2968 MI.eraseFromParent();
2971 case TargetOpcode::G_BSWAP: {
2975 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2976 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2977 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2980 MI.getOperand(0).setReg(DstExt);
2984 LLT Ty = MRI.getType(DstReg);
2986 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2987 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2993 case TargetOpcode::G_BITREVERSE: {
2997 LLT Ty = MRI.getType(DstReg);
3000 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
3002 MI.getOperand(0).setReg(DstExt);
3005 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
3006 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
3011 case TargetOpcode::G_FREEZE:
3012 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
3019 case TargetOpcode::G_ABS:
3026 case TargetOpcode::G_ADD:
3027 case TargetOpcode::G_AND:
3028 case TargetOpcode::G_MUL:
3029 case TargetOpcode::G_OR:
3030 case TargetOpcode::G_XOR:
3031 case TargetOpcode::G_SUB:
3032 case TargetOpcode::G_SHUFFLE_VECTOR:
3048 case TargetOpcode::G_SBFX:
3049 case TargetOpcode::G_UBFX:
3063 case TargetOpcode::G_SHL:
3083 case TargetOpcode::G_ROTR:
3084 case TargetOpcode::G_ROTL:
3093 case TargetOpcode::G_SDIV:
3094 case TargetOpcode::G_SREM:
3095 case TargetOpcode::G_SMIN:
3096 case TargetOpcode::G_SMAX:
3097 case TargetOpcode::G_ABDS:
3105 case TargetOpcode::G_SDIVREM:
3115 case TargetOpcode::G_ASHR:
3116 case TargetOpcode::G_LSHR:
3120 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3121 : TargetOpcode::G_ZEXT;
3134 case TargetOpcode::G_UDIV:
3135 case TargetOpcode::G_UREM:
3136 case TargetOpcode::G_ABDU:
3143 case TargetOpcode::G_UDIVREM:
3152 case TargetOpcode::G_UMIN:
3153 case TargetOpcode::G_UMAX: {
3154 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3156 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3160 ? TargetOpcode::G_SEXT
3161 : TargetOpcode::G_ZEXT;
3171 case TargetOpcode::G_SELECT:
3181 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3188 case TargetOpcode::G_FPEXT:
3196 case TargetOpcode::G_FPTOSI:
3197 case TargetOpcode::G_FPTOUI:
3198 case TargetOpcode::G_INTRINSIC_LRINT:
3199 case TargetOpcode::G_INTRINSIC_LLRINT:
3200 case TargetOpcode::G_IS_FPCLASS:
3210 case TargetOpcode::G_SITOFP:
3220 case TargetOpcode::G_UITOFP:
3230 case TargetOpcode::G_FPTOSI_SAT:
3231 case TargetOpcode::G_FPTOUI_SAT:
3236 LLT Ty = MRI.getType(OldDst);
3237 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3239 MI.getOperand(0).setReg(ExtReg);
3240 uint64_t ShortBits = Ty.getScalarSizeInBits();
3243 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3254 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3255 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3263 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3271 case TargetOpcode::G_LOAD:
3272 case TargetOpcode::G_SEXTLOAD:
3273 case TargetOpcode::G_ZEXTLOAD:
3274 case TargetOpcode::G_FPEXTLOAD:
3280 case TargetOpcode::G_STORE: {
3284 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3285 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3286 if (!Ty.isScalar()) {
3294 MI.setMemRefs(MF, {NewMMO});
3301 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3302 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3308 case TargetOpcode::G_FPTRUNCSTORE:
3315 case TargetOpcode::G_CONSTANT: {
3318 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3319 MRI.getType(
MI.getOperand(0).getReg()));
3320 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3321 ExtOpc == TargetOpcode::G_ANYEXT) &&
3324 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3328 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3334 case TargetOpcode::G_FCONSTANT: {
3340 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3342 MI.eraseFromParent();
3345 case TargetOpcode::G_IMPLICIT_DEF: {
3351 case TargetOpcode::G_BRCOND:
3357 case TargetOpcode::G_FCMP:
3368 case TargetOpcode::G_ICMP:
3373 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3377 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3378 unsigned ExtOpcode =
3382 ? TargetOpcode::G_SEXT
3383 : TargetOpcode::G_ZEXT;
3390 case TargetOpcode::G_PTR_ADD:
3391 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3397 case TargetOpcode::G_PHI: {
3398 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3401 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3404 OpMBB,
MI.getOperand(
I).getReg(), MRI));
3414 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3417 LLT VecTy = MRI.getType(VecReg);
3421 TargetOpcode::G_ANYEXT);
3435 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3451 LLT VecTy = MRI.getType(VecReg);
3470 case TargetOpcode::G_FADD:
3471 case TargetOpcode::G_FMUL:
3472 case TargetOpcode::G_FSUB:
3473 case TargetOpcode::G_FMA:
3474 case TargetOpcode::G_FMAD:
3475 case TargetOpcode::G_FNEG:
3476 case TargetOpcode::G_FABS:
3477 case TargetOpcode::G_FCANONICALIZE:
3478 case TargetOpcode::G_FMINNUM:
3479 case TargetOpcode::G_FMAXNUM:
3480 case TargetOpcode::G_FMINNUM_IEEE:
3481 case TargetOpcode::G_FMAXNUM_IEEE:
3482 case TargetOpcode::G_FMINIMUM:
3483 case TargetOpcode::G_FMAXIMUM:
3484 case TargetOpcode::G_FMINIMUMNUM:
3485 case TargetOpcode::G_FMAXIMUMNUM:
3486 case TargetOpcode::G_FDIV:
3487 case TargetOpcode::G_FREM:
3488 case TargetOpcode::G_FCEIL:
3489 case TargetOpcode::G_FFLOOR:
3490 case TargetOpcode::G_FCOS:
3491 case TargetOpcode::G_FSIN:
3492 case TargetOpcode::G_FTAN:
3493 case TargetOpcode::G_FACOS:
3494 case TargetOpcode::G_FASIN:
3495 case TargetOpcode::G_FATAN:
3496 case TargetOpcode::G_FATAN2:
3497 case TargetOpcode::G_FCOSH:
3498 case TargetOpcode::G_FSINH:
3499 case TargetOpcode::G_FTANH:
3500 case TargetOpcode::G_FLOG10:
3501 case TargetOpcode::G_FLOG:
3502 case TargetOpcode::G_FLOG2:
3503 case TargetOpcode::G_FRINT:
3504 case TargetOpcode::G_FNEARBYINT:
3505 case TargetOpcode::G_FSQRT:
3506 case TargetOpcode::G_FEXP:
3507 case TargetOpcode::G_FEXP2:
3508 case TargetOpcode::G_FEXP10:
3509 case TargetOpcode::G_FPOW:
3510 case TargetOpcode::G_INTRINSIC_TRUNC:
3511 case TargetOpcode::G_INTRINSIC_ROUND:
3512 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3516 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3522 case TargetOpcode::G_FMODF: {
3532 case TargetOpcode::G_FPOWI:
3533 case TargetOpcode::G_FLDEXP:
3534 case TargetOpcode::G_STRICT_FLDEXP: {
3536 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3557 case TargetOpcode::G_FFREXP: {
3570 case TargetOpcode::G_LROUND:
3571 case TargetOpcode::G_LLROUND:
3582 case TargetOpcode::G_INTTOPTR:
3590 case TargetOpcode::G_PTRTOINT:
3598 case TargetOpcode::G_BUILD_VECTOR: {
3602 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3608 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3616 case TargetOpcode::G_SEXT_INREG:
3625 case TargetOpcode::G_PTRMASK: {
3633 case TargetOpcode::G_VECREDUCE_ADD: {
3642 case TargetOpcode::G_VECREDUCE_FADD:
3643 case TargetOpcode::G_VECREDUCE_FMUL:
3644 case TargetOpcode::G_VECREDUCE_FMIN:
3645 case TargetOpcode::G_VECREDUCE_FMAX:
3646 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3647 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3652 LLT VecTy = MRI.getType(VecReg);
3659 case TargetOpcode::G_VSCALE: {
3666 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3671 case TargetOpcode::G_SPLAT_VECTOR: {
3680 case TargetOpcode::G_INSERT_SUBVECTOR: {
3692 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3693 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3694 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3698 auto SplatZero =
MIRBuilder.buildSplatVector(
3703 MI.eraseFromParent();
3707 case TargetOpcode::G_BITCAST:
3719 if (MRI.getType(Dst) == MRI.getType(Src)) {
3720 Observer.changingAllUsesOfReg(MRI, Dst);
3721 MRI.replaceRegWith(Dst, Src);
3722 Observer.finishedChangingAllUsesOfReg();
3723 MI.eraseFromParent();
3732 auto Unmerge =
B.buildUnmerge(Ty, Src);
3733 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3742 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3744 LLT DstLLT =
MRI.getType(DstReg);
3756 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3765 MI.eraseFromParent();
3773 const ConstantFP *ConstantVal =
MI.getOperand(1).getFPImm();
3776 bool ForCodeSize =
MIRBuilder.getMF().getFunction().hasOptSize();
3777 if (TLI.getFPImmAction(
Imm, MRI.getType(Dst), ForCodeSize) ==
3783 MI.eraseFromParent();
3789 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3790 if (SrcTy.isVector()) {
3794 if (DstTy.isVector()) {
3809 unsigned PieceSize =
3825 MI.eraseFromParent();
3830 LLT::vector(SrcEC * (SrcEltSize / PieceSize), PieceTy);
3832 MIRBuilder.buildBitcast(PiecesVecTy, Src).getReg(0);
3834 MI.eraseFromParent();
3841 LLT DstCastTy = DstEltTy;
3842 LLT SrcPartTy = SrcEltTy;
3846 if (NumSrcElt < NumDstElt) {
3857 SrcPartTy = SrcEltTy;
3858 }
else if (NumSrcElt > NumDstElt) {
3870 DstCastTy = DstEltTy;
3875 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3879 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3880 MI.eraseFromParent();
3884 if (DstTy.isVector()) {
3887 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3888 MI.eraseFromParent();
3904 unsigned NewEltSize,
3905 unsigned OldEltSize) {
3906 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3907 LLT IdxTy =
B.getMRI()->getType(Idx);
3910 auto OffsetMask =
B.buildConstant(
3912 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3913 return B.buildShl(IdxTy, OffsetIdx,
3914 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3929 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3933 unsigned OldNumElts = SrcVecTy.getNumElements();
3940 if (NewNumElts > OldNumElts) {
3951 if (NewNumElts % OldNumElts != 0)
3955 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3959 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3962 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3964 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3965 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3966 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3967 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3968 NewOps[
I] = Elt.getReg(0);
3971 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3973 MI.eraseFromParent();
3977 if (NewNumElts < OldNumElts) {
3978 if (NewEltSize % OldEltSize != 0)
4000 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4001 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4004 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4008 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4009 ScaledIdx).getReg(0);
4017 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
4019 MI.eraseFromParent();
4033 LLT TargetTy =
B.getMRI()->getType(TargetReg);
4034 LLT InsertTy =
B.getMRI()->getType(InsertReg);
4035 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
4036 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
4039 auto EltMask =
B.buildConstant(
4043 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
4044 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
4047 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
4051 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
4065 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
4066 MI.getFirst4RegLLTs();
4078 if (NewNumElts < OldNumElts) {
4079 if (NewEltSize % OldEltSize != 0)
4088 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4089 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4092 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4096 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4097 ScaledIdx).getReg(0);
4107 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4108 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4112 MI.eraseFromParent();
4142 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4146 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4147 return UnableToLegalize;
4152 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4154 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4163 MI.eraseFromParent();
4181 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4182 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4192 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4193 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4195 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4196 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4198 MI.eraseFromParent();
4224 uint64_t Idx = ES->getIndexImm();
4228 LLT DstTy = MRI.getType(Dst);
4229 LLT SrcTy = MRI.getType(Src);
4235 if (DstTy == CastTy)
4243 if (CastEltSize < DstEltSize)
4246 auto AdjustAmt = CastEltSize / DstEltSize;
4247 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4248 SrcTyMinElts % AdjustAmt != 0)
4253 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4254 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4257 ES->eraseFromParent();
4288 uint64_t Idx = ES->getIndexImm();
4292 LLT DstTy = MRI.getType(Dst);
4293 LLT BigVecTy = MRI.getType(BigVec);
4296 if (DstTy == CastTy)
4311 if (CastEltSize < DstEltSize)
4314 auto AdjustAmt = CastEltSize / DstEltSize;
4315 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4316 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4322 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4325 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4328 ES->eraseFromParent();
4336 LLT DstTy = MRI.getType(DstReg);
4346 if (MemSizeInBits != MemStoreSizeInBits) {
4363 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4367 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4368 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4370 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4373 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4375 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4378 if (DstTy != LoadTy)
4386 if (
MIRBuilder.getDataLayout().isBigEndian())
4404 uint64_t LargeSplitSize, SmallSplitSize;
4409 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4416 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4419 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4430 if (Alignment.value() * 8 > MemSizeInBits &&
4435 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4452 LLT PtrTy = MRI.getType(PtrReg);
4458 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4461 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4462 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4463 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4465 SmallPtr, *SmallMMO);
4467 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4468 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4470 if (AnyExtTy == DstTy)
4471 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4473 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4475 if (IntDstTy == DstTy) {
4482 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4488 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4505 LLT SrcTy = MRI.getType(SrcReg);
4513 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4519 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4521 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4525 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4529 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4544 uint64_t LargeSplitSize, SmallSplitSize;
4551 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4554 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4563 if (SrcTy.isPointer()) {
4568 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4571 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4572 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4575 LLT PtrTy = MRI.getType(PtrReg);
4577 LargeSplitSize / 8);
4578 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4584 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4585 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4594 LLT SrcTy = MRI.getType(SrcReg);
4600 assert(SrcTy.isVector() &&
"Expect a vector store type");
4607 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4611 auto Elt =
MIRBuilder.buildExtractVectorElement(
4612 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4613 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4614 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4620 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4621 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4625 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4636 switch (
MI.getOpcode()) {
4637 case TargetOpcode::G_LOAD: {
4655 case TargetOpcode::G_STORE: {
4671 case TargetOpcode::G_SELECT: {
4675 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4677 dbgs() <<
"bitcast action not implemented for vector select\n");
4688 case TargetOpcode::G_AND:
4689 case TargetOpcode::G_OR:
4690 case TargetOpcode::G_XOR: {
4698 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4700 case TargetOpcode::G_INSERT_VECTOR_ELT:
4702 case TargetOpcode::G_CONCAT_VECTORS:
4704 case TargetOpcode::G_SHUFFLE_VECTOR:
4706 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4708 case TargetOpcode::G_INSERT_SUBVECTOR:
4716void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4725 switch(
MI.getOpcode()) {
4728 case TargetOpcode::G_FCONSTANT:
4730 case TargetOpcode::G_BITCAST:
4732 case TargetOpcode::G_SREM:
4733 case TargetOpcode::G_UREM: {
4734 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4736 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4737 {MI.getOperand(1), MI.getOperand(2)});
4739 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4741 MI.eraseFromParent();
4744 case TargetOpcode::G_SADDO:
4745 case TargetOpcode::G_SSUBO:
4747 case TargetOpcode::G_SADDE:
4749 case TargetOpcode::G_SSUBE:
4751 case TargetOpcode::G_UMULH:
4752 case TargetOpcode::G_SMULH:
4754 case TargetOpcode::G_SMULO:
4755 case TargetOpcode::G_UMULO: {
4758 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4759 LLT Ty = MRI.getType(Res);
4761 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4762 ? TargetOpcode::G_SMULH
4763 : TargetOpcode::G_UMULH;
4767 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4768 MI.removeOperand(1);
4771 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4779 if (Opcode == TargetOpcode::G_SMULH) {
4780 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4781 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4788 case TargetOpcode::G_FNEG: {
4789 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4792 Register CastedSubByReg = SubByReg;
4794 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4795 !SubByRegTy.getScalarType().isInteger()) {
4796 auto BitcastDst = SubByRegTy.changeElementType(
4798 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4804 if (ResTy != TyInt) {
4806 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4809 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4811 MI.eraseFromParent();
4814 case TargetOpcode::G_FSUB:
4815 case TargetOpcode::G_STRICT_FSUB: {
4816 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4817 LLT Ty = MRI.getType(Res);
4822 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4823 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4827 MI.eraseFromParent();
4830 case TargetOpcode::G_FMAD:
4832 case TargetOpcode::G_FFLOOR:
4834 case TargetOpcode::G_LROUND:
4835 case TargetOpcode::G_LLROUND: {
4838 LLT SrcTy = MRI.getType(SrcReg);
4839 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4842 MI.eraseFromParent();
4845 case TargetOpcode::G_INTRINSIC_ROUND:
4847 case TargetOpcode::G_FRINT: {
4850 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4853 case TargetOpcode::G_INTRINSIC_LRINT:
4854 case TargetOpcode::G_INTRINSIC_LLRINT: {
4857 LLT SrcTy = MRI.getType(SrcReg);
4859 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4861 MI.eraseFromParent();
4864 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4865 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4866 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4867 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4868 **
MI.memoperands_begin());
4870 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4871 MI.eraseFromParent();
4874 case TargetOpcode::G_LOAD:
4875 case TargetOpcode::G_SEXTLOAD:
4876 case TargetOpcode::G_ZEXTLOAD:
4878 case TargetOpcode::G_STORE:
4880 case TargetOpcode::G_CTLZ_ZERO_POISON:
4881 case TargetOpcode::G_CTTZ_ZERO_POISON:
4882 case TargetOpcode::G_CTLZ:
4883 case TargetOpcode::G_CTTZ:
4884 case TargetOpcode::G_CTPOP:
4885 case TargetOpcode::G_CTLS:
4888 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4890 Register NewRes = MRI.cloneVirtualRegister(Res);
4897 MI.eraseFromParent();
4901 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4902 const LLT CondTy = MRI.getType(CarryOut);
4903 const LLT Ty = MRI.getType(Res);
4905 Register NewRes = MRI.cloneVirtualRegister(Res);
4908 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4914 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4915 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4922 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4927 MI.eraseFromParent();
4931 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4936 MI.eraseFromParent();
4940 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4941 const LLT CondTy = MRI.getType(BorrowOut);
4942 const LLT Ty = MRI.getType(Res);
4945 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4951 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4952 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4959 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4960 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4962 MI.eraseFromParent();
5002 case G_MERGE_VALUES:
5004 case G_UNMERGE_VALUES:
5006 case TargetOpcode::G_SEXT_INREG: {
5007 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
5008 int64_t SizeInBits =
MI.getOperand(2).getImm();
5010 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
5011 LLT DstTy = MRI.getType(DstReg);
5012 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
5015 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
5016 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
5017 MI.eraseFromParent();
5020 case G_EXTRACT_VECTOR_ELT:
5021 case G_INSERT_VECTOR_ELT:
5023 case G_SHUFFLE_VECTOR:
5025 case G_VECTOR_COMPRESS:
5027 case G_DYN_STACKALLOC:
5029 case G_INSERT_SUBVECTOR: {
5030 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
5031 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
5036 Register Subvector =
MI.getOperand(2).getReg();
5037 auto InsertionPointImm =
MI.getOperand(3).getImm();
5040 LLT DstTy = MRI.getType(Subvector);
5044 bool InsertInLowHalf = InsertionPointImm == 0;
5045 auto Extract =
MIRBuilder.buildExtractSubvector(
5047 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
5049 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
5050 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
5052 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
5053 {LowHalf, HighHalf});
5054 MI.eraseFromParent();
5060 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
5061 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
5067 if (i >= InsertionPointImm &&
5069 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
5077 MI.eraseFromParent();
5081 case G_EXTRACT_SUBVECTOR: {
5084 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5086 LLT SrcTy = MRI.getType(SrcReg);
5087 LLT DstTy = MRI.getType(DstReg);
5089 if (SrcTy.isScalable())
5100 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5101 ExtractionPointImm + i)
5105 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5106 MI.eraseFromParent();
5111 case G_STACKRESTORE:
5121 case G_READ_REGISTER:
5122 case G_WRITE_REGISTER:
5129 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5130 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5136 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5141 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5148 case G_TRUNC_SSAT_S:
5149 case G_TRUNC_USAT_U:
5150 case G_TRUNC_SSAT_U:
5156 bool IsSigned =
MI.getOpcode() == G_ABDS;
5157 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5158 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5159 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5182 case G_MEMCPY_INLINE:
5183 case G_MEMSET_INLINE:
5195 case G_ATOMICRMW_SUB: {
5196 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5197 const LLT ValTy = MRI.getType(Val);
5201 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5202 MI.eraseFromParent();
5230 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5234 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5240 Align StackTypeAlign =
5247 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5248 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5253 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5265 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5268 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5279 "Converting bits to bytes lost precision");
5285 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5286 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5288 if (IdxTy != MRI.getType(Index))
5289 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5294 LLT PtrTy = MRI.getType(VecPtr);
5295 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5303 std::initializer_list<unsigned> NonVecOpIndices) {
5304 if (
MI.getNumMemOperands() != 0)
5307 LLT VecTy =
MRI.getType(
MI.getReg(0));
5312 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5321 if (!Ty.isVector()) {
5327 if (Ty.getNumElements() != NumElts)
5342 assert(Ty.isVector() &&
"Expected vector type");
5349 for (
int i = 0; i <
NumParts; ++i) {
5354 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5363 for (
unsigned i = 0; i <
N; ++i) {
5365 Ops.push_back(
Op.getReg());
5366 else if (
Op.isImm())
5367 Ops.push_back(
Op.getImm());
5368 else if (
Op.isPredicate())
5390 std::initializer_list<unsigned> NonVecOpIndices) {
5392 "Non-compatible opcode or not specified non-vector operands");
5393 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5395 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5396 unsigned NumDefs =
MI.getNumDefs();
5404 for (
unsigned i = 0; i < NumDefs; ++i) {
5405 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5413 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5414 ++UseIdx, ++UseNo) {
5417 MI.getOperand(UseIdx));
5426 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5430 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5432 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5433 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5436 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5437 Uses.push_back(InputOpsPieces[InputNo][i]);
5440 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5441 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5446 for (
unsigned i = 0; i < NumDefs; ++i)
5447 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5449 for (
unsigned i = 0; i < NumDefs; ++i)
5450 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5453 MI.eraseFromParent();
5460 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5462 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5463 unsigned NumDefs =
MI.getNumDefs();
5467 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5472 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5473 UseIdx += 2, ++UseNo) {
5482 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5484 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5485 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5487 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5490 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5491 Phi.addUse(InputOpsPieces[j][i]);
5492 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5502 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5504 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5507 MI.eraseFromParent();
5515 const int NumDst =
MI.getNumOperands() - 1;
5516 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5517 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5518 LLT SrcTy = MRI.getType(SrcReg);
5520 if (TypeIdx != 1 || NarrowTy == DstTy)
5527 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5530 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5544 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5545 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5546 const int PartsPerUnmerge = NumDst / NumUnmerge;
5548 for (
int I = 0;
I != NumUnmerge; ++
I) {
5549 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5551 for (
int J = 0; J != PartsPerUnmerge; ++J)
5552 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5553 MIB.addUse(Unmerge.getReg(
I));
5556 MI.eraseFromParent();
5563 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5567 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5569 if (NarrowTy == SrcTy)
5577 assert(SrcTy.isVector() &&
"Expected vector types");
5579 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5593 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5594 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5595 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5601 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5602 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5603 ++i,
Offset += NumNarrowTyElts) {
5606 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5609 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5610 MI.eraseFromParent();
5614 assert(TypeIdx == 0 &&
"Bad type index");
5615 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5631 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5633 for (
unsigned i = 0; i <
NumParts; ++i) {
5635 for (
unsigned j = 0; j < NumElts; ++j)
5636 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5638 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5641 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5642 MI.eraseFromParent();
5650 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5652 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5654 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5656 InsertVal =
MI.getOperand(2).getReg();
5658 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5659 LLT VecTy = MRI.getType(SrcVec);
5665 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5669 MI.eraseFromParent();
5678 SplitPieces[IdxVal] = InsertVal;
5679 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5681 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5685 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5688 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5689 TargetOpcode::G_ANYEXT);
5693 LLT IdxTy = MRI.getType(Idx);
5694 int64_t PartIdx = IdxVal / NewNumElts;
5696 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5699 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5702 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5703 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5704 VecParts[PartIdx] = InsertPart.getReg(0);
5708 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5710 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5714 MI.eraseFromParent();
5734 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5746 LLT ValTy = MRI.getType(ValReg);
5755 int NumLeftover = -1;
5761 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5764 NumLeftover = NarrowLeftoverRegs.
size();
5771 LLT PtrTy = MRI.getType(AddrReg);
5781 auto MMO = LdStMI.
getMMO();
5786 for (
unsigned Idx = 0, E =
NumParts; Idx != E &&
Offset < TotalSize;
5788 unsigned ByteOffset =
Offset / 8;
5791 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5798 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5799 ValRegs.push_back(Dst);
5800 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5802 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5811 unsigned HandledOffset =
5816 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5819 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5820 LeftoverTy, NarrowLeftoverRegs);
5834 switch (
MI.getOpcode()) {
5835 case G_IMPLICIT_DEF:
5851 case G_FCANONICALIZE:
5868 case G_INTRINSIC_LRINT:
5869 case G_INTRINSIC_LLRINT:
5870 case G_INTRINSIC_ROUND:
5871 case G_INTRINSIC_ROUNDEVEN:
5874 case G_INTRINSIC_TRUNC:
5902 case G_FMINNUM_IEEE:
5903 case G_FMAXNUM_IEEE:
5925 case G_CTLZ_ZERO_POISON:
5927 case G_CTTZ_ZERO_POISON:
5944 case G_ADDRSPACE_CAST:
5957 case G_STRICT_FLDEXP:
5959 case G_TRUNC_SSAT_S:
5960 case G_TRUNC_SSAT_U:
5961 case G_TRUNC_USAT_U:
5969 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5974 case G_UNMERGE_VALUES:
5976 case G_BUILD_VECTOR:
5977 assert(TypeIdx == 0 &&
"not a vector type index");
5979 case G_CONCAT_VECTORS:
5983 case G_EXTRACT_SUBVECTOR: {
5985 LLT DstTy = MRI.getType(DstReg);
5987 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5997 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5998 uint64_t RequiredSubvectorIndex =
6002 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
6005 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
6008 MI.eraseFromParent();
6011 case G_EXTRACT_VECTOR_ELT:
6012 case G_INSERT_VECTOR_ELT:
6021 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
6022 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
6024 case G_SHUFFLE_VECTOR:
6030 case G_INTRINSIC_FPTRUNC_ROUND:
6040 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
6041 "Not a bitcast operation");
6046 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6048 unsigned NewElemCount =
6051 if (NewElemCount == 1) {
6054 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
6061 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
6070 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
6071 MI.eraseFromParent();
6077 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6081 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6082 MI.getFirst3RegLLTs();
6085 if (DstTy != Src1Ty)
6087 if (DstTy != Src2Ty)
6102 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6118 unsigned InputUsed[2] = {-1U, -1U};
6119 unsigned FirstMaskIdx =
High * NewElts;
6120 bool UseBuildVector =
false;
6121 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6123 int Idx = Mask[FirstMaskIdx + MaskOffset];
6128 if (
Input >= std::size(Inputs)) {
6135 Idx -=
Input * NewElts;
6139 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6140 if (InputUsed[OpNo] ==
Input) {
6143 }
else if (InputUsed[OpNo] == -1U) {
6145 InputUsed[OpNo] =
Input;
6150 if (OpNo >= std::size(InputUsed)) {
6153 UseBuildVector =
true;
6158 Ops.push_back(Idx + OpNo * NewElts);
6161 if (UseBuildVector) {
6166 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6168 int Idx = Mask[FirstMaskIdx + MaskOffset];
6173 if (
Input >= std::size(Inputs)) {
6180 Idx -=
Input * NewElts;
6184 .buildExtractVectorElement(
6185 EltTy, Inputs[
Input],
6191 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6192 }
else if (InputUsed[0] == -1U) {
6194 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6195 }
else if (NewElts == 1) {
6196 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6198 Register Op0 = Inputs[InputUsed[0]];
6202 : Inputs[InputUsed[1]];
6204 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6211 MI.eraseFromParent();
6224 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6230 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6235 : SrcTy.getNumElements();
6239 if (DstTy != NarrowTy)
6246 while (NumPartsLeft > 1) {
6247 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6250 .buildInstr(ScalarOpc, {NarrowTy},
6251 {SplitSrcs[Idx], SplitSrcs[Idx + 1]},
6255 SplitSrcs = PartialResults;
6256 PartialResults.
clear();
6257 NumPartsLeft = SplitSrcs.
size();
6261 MI.eraseFromParent();
6266 for (
unsigned Idx = 1; Idx <
NumParts; ++Idx)
6268 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]},
6272 MI.eraseFromParent();
6276 for (
unsigned Part = 0; Part <
NumParts; ++Part) {
6278 .buildInstr(RdxMI.getOpcode(), {DstTy},
6288 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6291 Register Acc = PartialReductions[0];
6292 for (
unsigned Part = 1; Part <
NumParts; ++Part) {
6294 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, {Acc, PartialReductions[Part]},
6298 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]},
6303 MI.eraseFromParent();
6309 unsigned int TypeIdx,
6311 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6312 MI.getFirst3RegLLTs();
6313 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6317 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6318 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6319 "Unexpected vecreduce opcode");
6320 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6321 ? TargetOpcode::G_FADD
6322 : TargetOpcode::G_FMUL;
6325 unsigned NumParts = SrcTy.getNumElements();
6328 for (
unsigned i = 0; i <
NumParts; i++)
6330 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]},
6335 MI.eraseFromParent();
6342 unsigned ScalarOpc) {
6350 while (SplitSrcs.
size() > 1) {
6352 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6362 SplitSrcs = std::move(PartialRdxs);
6366 MI.getOperand(1).setReg(SplitSrcs[0]);
6373 const LLT HalfTy,
const LLT AmtTy) {
6375 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6376 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6380 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6381 MI.eraseFromParent();
6387 unsigned VTBits = 2 * NVTBits;
6390 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6391 if (Amt.
ugt(VTBits)) {
6393 }
else if (Amt.
ugt(NVTBits)) {
6396 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6397 }
else if (Amt == NVTBits) {
6405 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6408 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6409 if (Amt.
ugt(VTBits)) {
6411 }
else if (Amt.
ugt(NVTBits)) {
6413 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6415 }
else if (Amt == NVTBits) {
6419 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6421 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6423 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6429 if (Amt.
ugt(VTBits)) {
6431 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6432 }
else if (Amt.
ugt(NVTBits)) {
6434 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6436 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6437 }
else if (Amt == NVTBits) {
6440 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6442 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6444 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6446 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6453 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6454 MI.eraseFromParent();
6470 LLT DstTy = MRI.getType(DstReg);
6475 LLT ShiftAmtTy = MRI.getType(Amt);
6477 if (DstEltSize % 2 != 0)
6504 const unsigned NewBitSize = DstEltSize / 2;
6516 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6518 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6519 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6522 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6523 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6530 switch (
MI.getOpcode()) {
6531 case TargetOpcode::G_SHL: {
6533 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6535 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6536 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6537 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6540 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6541 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6543 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6545 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6547 ResultRegs[0] =
Lo.getReg(0);
6548 ResultRegs[1] =
Hi.getReg(0);
6551 case TargetOpcode::G_LSHR:
6552 case TargetOpcode::G_ASHR: {
6554 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6556 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6557 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6558 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6562 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6565 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6566 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6568 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6572 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6574 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6576 ResultRegs[0] =
Lo.getReg(0);
6577 ResultRegs[1] =
Hi.getReg(0);
6584 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6585 MI.eraseFromParent();
6594 LLT TargetTy,
LLT ShiftAmtTy) {
6597 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6599 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6600 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6601 const bool NeedsInterWordShift = ShiftBits != 0;
6604 case TargetOpcode::G_SHL: {
6607 if (PartIdx < ShiftWords)
6610 unsigned SrcIdx = PartIdx - ShiftWords;
6611 if (!NeedsInterWordShift)
6612 return SrcParts[SrcIdx];
6617 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6621 return Hi.getReg(0);
6624 case TargetOpcode::G_LSHR: {
6625 unsigned SrcIdx = PartIdx + ShiftWords;
6628 if (!NeedsInterWordShift)
6629 return SrcParts[SrcIdx];
6634 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6638 return Lo.getReg(0);
6641 case TargetOpcode::G_ASHR: {
6643 unsigned SrcIdx = PartIdx + ShiftWords;
6646 if (!NeedsInterWordShift)
6647 return SrcParts[SrcIdx];
6678 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6679 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6684 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6693 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6694 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6696 auto IsZeroBitShift =
6704 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6705 : TargetOpcode::G_SHL;
6708 auto TargetBitsConst =
6710 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6715 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6720 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6722 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6726 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6739 LLT DstTy = MRI.getType(DstReg);
6743 const unsigned NumParts = DstBits / TargetBits;
6745 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6755 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6756 MI.eraseFromParent();
6761 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6762 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6768 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6772 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6775 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6776 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6782 Params, TargetTy, ShiftAmtTy);
6784 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6785 MI.eraseFromParent();
6794 LLT DstTy = MRI.getType(DstReg);
6795 LLT ShiftAmtTy = MRI.getType(AmtReg);
6799 const unsigned NumParts = DstBits / TargetBits;
6801 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6818 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6830 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6831 auto TargetBitsLog2Const =
6832 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6833 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6836 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6838 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6846 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6847 auto TargetBitsMinusOneConst =
6848 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6850 .buildAShr(TargetTy, SrcParts[
NumParts - 1],
6851 TargetBitsMinusOneConst)
6854 FillValue = ZeroReg;
6864 Register InBoundsResult = FillValue;
6875 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy,
K);
6877 WordShift, WordShiftKConst);
6889 switch (
MI.getOpcode()) {
6890 case TargetOpcode::G_SHL:
6891 MainSrcIdx = (int)
I - (
int)
K;
6892 CarrySrcIdx = MainSrcIdx - 1;
6894 case TargetOpcode::G_LSHR:
6895 case TargetOpcode::G_ASHR:
6896 MainSrcIdx = (int)
I + (
int)
K;
6897 CarrySrcIdx = MainSrcIdx + 1;
6905 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)
NumParts) {
6906 Register MainOp = SrcParts[MainSrcIdx];
6910 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)
NumParts)
6911 CarryOp = SrcParts[CarrySrcIdx];
6912 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6914 CarryOp = FillValue;
6920 ResultForK = FillValue;
6926 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6933 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6937 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6938 MI.eraseFromParent();
6945 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6948 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6951 OpMBB,
MI.getOperand(
I).getReg(), MRI));
6964 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6969 "getNeutralElementForVecReduce called with invalid opcode!");
6970 case TargetOpcode::G_VECREDUCE_ADD:
6971 case TargetOpcode::G_VECREDUCE_OR:
6972 case TargetOpcode::G_VECREDUCE_XOR:
6973 case TargetOpcode::G_VECREDUCE_UMAX:
6975 case TargetOpcode::G_VECREDUCE_MUL:
6977 case TargetOpcode::G_VECREDUCE_AND:
6978 case TargetOpcode::G_VECREDUCE_UMIN:
6981 case TargetOpcode::G_VECREDUCE_SMAX:
6984 case TargetOpcode::G_VECREDUCE_SMIN:
6987 case TargetOpcode::G_VECREDUCE_FADD:
6989 case TargetOpcode::G_VECREDUCE_FMUL:
6991 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6992 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6993 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6994 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
7002 unsigned Opc =
MI.getOpcode();
7004 case TargetOpcode::G_IMPLICIT_DEF:
7005 case TargetOpcode::G_LOAD: {
7013 case TargetOpcode::G_STORE:
7020 case TargetOpcode::G_AND:
7021 case TargetOpcode::G_OR:
7022 case TargetOpcode::G_XOR:
7023 case TargetOpcode::G_ADD:
7024 case TargetOpcode::G_SUB:
7025 case TargetOpcode::G_MUL:
7026 case TargetOpcode::G_FADD:
7027 case TargetOpcode::G_FSUB:
7028 case TargetOpcode::G_FMUL:
7029 case TargetOpcode::G_FDIV:
7030 case TargetOpcode::G_FCOPYSIGN:
7031 case TargetOpcode::G_UADDSAT:
7032 case TargetOpcode::G_USUBSAT:
7033 case TargetOpcode::G_SADDSAT:
7034 case TargetOpcode::G_SSUBSAT:
7035 case TargetOpcode::G_SMIN:
7036 case TargetOpcode::G_SMAX:
7037 case TargetOpcode::G_UMIN:
7038 case TargetOpcode::G_UMAX:
7039 case TargetOpcode::G_FMINNUM:
7040 case TargetOpcode::G_FMAXNUM:
7041 case TargetOpcode::G_FMINNUM_IEEE:
7042 case TargetOpcode::G_FMAXNUM_IEEE:
7043 case TargetOpcode::G_FMINIMUM:
7044 case TargetOpcode::G_FMAXIMUM:
7045 case TargetOpcode::G_FMINIMUMNUM:
7046 case TargetOpcode::G_FMAXIMUMNUM:
7047 case TargetOpcode::G_STRICT_FADD:
7048 case TargetOpcode::G_STRICT_FSUB:
7049 case TargetOpcode::G_STRICT_FMUL: {
7057 case TargetOpcode::G_SHL:
7058 case TargetOpcode::G_ASHR:
7059 case TargetOpcode::G_LSHR: {
7065 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
7071 case TargetOpcode::G_FMA:
7072 case TargetOpcode::G_STRICT_FMA:
7073 case TargetOpcode::G_FSHR:
7074 case TargetOpcode::G_FSHL: {
7083 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
7084 case TargetOpcode::G_EXTRACT:
7091 case TargetOpcode::G_INSERT:
7092 case TargetOpcode::G_INSERT_VECTOR_ELT:
7093 case TargetOpcode::G_FREEZE:
7094 case TargetOpcode::G_FNEG:
7095 case TargetOpcode::G_FABS:
7096 case TargetOpcode::G_FSQRT:
7097 case TargetOpcode::G_FCEIL:
7098 case TargetOpcode::G_FFLOOR:
7099 case TargetOpcode::G_FNEARBYINT:
7100 case TargetOpcode::G_FRINT:
7101 case TargetOpcode::G_INTRINSIC_ROUND:
7102 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7103 case TargetOpcode::G_INTRINSIC_TRUNC:
7104 case TargetOpcode::G_BITREVERSE:
7105 case TargetOpcode::G_BSWAP:
7106 case TargetOpcode::G_FCANONICALIZE:
7107 case TargetOpcode::G_SEXT_INREG:
7108 case TargetOpcode::G_ABS:
7109 case TargetOpcode::G_CTLZ:
7110 case TargetOpcode::G_CTPOP:
7118 case TargetOpcode::G_SELECT: {
7119 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7121 if (!CondTy.isScalar() ||
7127 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7129 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7134 if (CondTy.isVector())
7144 case TargetOpcode::G_UNMERGE_VALUES:
7146 case TargetOpcode::G_PHI:
7148 case TargetOpcode::G_SHUFFLE_VECTOR:
7150 case TargetOpcode::G_BUILD_VECTOR: {
7152 for (
auto Op :
MI.uses()) {
7160 MIRBuilder.buildDeleteTrailingVectorElements(
7161 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7162 MI.eraseFromParent();
7165 case TargetOpcode::G_SEXT:
7166 case TargetOpcode::G_ZEXT:
7167 case TargetOpcode::G_ANYEXT:
7168 case TargetOpcode::G_TRUNC:
7169 case TargetOpcode::G_FPTRUNC:
7170 case TargetOpcode::G_FPEXT:
7171 case TargetOpcode::G_FPTOSI:
7172 case TargetOpcode::G_FPTOUI:
7173 case TargetOpcode::G_FPTOSI_SAT:
7174 case TargetOpcode::G_FPTOUI_SAT:
7175 case TargetOpcode::G_SITOFP:
7176 case TargetOpcode::G_UITOFP:
7177 case TargetOpcode::G_TRUNC_SSAT_S:
7178 case TargetOpcode::G_TRUNC_SSAT_U:
7179 case TargetOpcode::G_TRUNC_USAT_U: {
7186 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7189 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7197 case TargetOpcode::G_ICMP:
7198 case TargetOpcode::G_FCMP: {
7206 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7211 case TargetOpcode::G_BITCAST: {
7215 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7216 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7232 case TargetOpcode::G_VECREDUCE_FADD:
7233 case TargetOpcode::G_VECREDUCE_FMUL:
7234 case TargetOpcode::G_VECREDUCE_ADD:
7235 case TargetOpcode::G_VECREDUCE_MUL:
7236 case TargetOpcode::G_VECREDUCE_AND:
7237 case TargetOpcode::G_VECREDUCE_OR:
7238 case TargetOpcode::G_VECREDUCE_XOR:
7239 case TargetOpcode::G_VECREDUCE_SMAX:
7240 case TargetOpcode::G_VECREDUCE_SMIN:
7241 case TargetOpcode::G_VECREDUCE_UMAX:
7242 case TargetOpcode::G_VECREDUCE_UMIN: {
7243 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7245 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7246 auto NeutralElement = getNeutralElementForVecReduce(
7252 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7253 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7254 NeutralElement, Idx);
7258 MO.
setReg(NewVec.getReg(0));
7270 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7272 unsigned MaskNumElts = Mask.size();
7273 unsigned SrcNumElts = SrcTy.getNumElements();
7276 if (MaskNumElts == SrcNumElts)
7279 if (MaskNumElts < SrcNumElts) {
7287 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7288 MI.getOperand(1).getReg(),
7289 MI.getOperand(2).getReg(), NewMask);
7290 MI.eraseFromParent();
7295 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7296 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7305 MOps1[0] =
MI.getOperand(1).getReg();
7306 MOps2[0] =
MI.getOperand(2).getReg();
7308 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7309 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7313 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7315 if (Idx >=
static_cast<int>(SrcNumElts))
7316 Idx += PaddedMaskNumElts - SrcNumElts;
7321 if (MaskNumElts != PaddedMaskNumElts) {
7323 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7326 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7328 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7333 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7336 MI.eraseFromParent();
7342 unsigned int TypeIdx,
LLT MoreTy) {
7343 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7345 unsigned NumElts = DstTy.getNumElements();
7348 if (DstTy.isVector() && Src1Ty.isVector() &&
7349 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7357 if (DstTy != Src1Ty || DstTy != Src2Ty)
7365 for (
unsigned I = 0;
I != NumElts; ++
I) {
7367 if (Idx <
static_cast<int>(NumElts))
7370 NewMask[
I] = Idx - NumElts + WidenNumElts;
7374 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7375 MI.getOperand(1).getReg(),
7376 MI.getOperand(2).getReg(), NewMask);
7377 MI.eraseFromParent();
7386 unsigned SrcParts = Src1Regs.
size();
7387 unsigned DstParts = DstRegs.
size();
7389 unsigned DstIdx = 0;
7391 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7392 DstRegs[DstIdx] = FactorSum;
7397 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7399 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7400 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7402 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7408 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7409 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7410 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7411 unsigned i = RevI - 1;
7413 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7423 if (DstIdx != DstParts - 1) {
7424 MachineInstrBuilder Uaddo =
7425 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7426 FactorSum = Uaddo.
getReg(0);
7427 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7428 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7429 MachineInstrBuilder Uaddo =
7430 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7431 FactorSum = Uaddo.
getReg(0);
7432 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7433 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7437 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7438 for (
unsigned i = 2; i < Factors.
size(); ++i)
7439 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7442 CarrySumPrevDstIdx = CarrySum;
7443 DstRegs[DstIdx] = FactorSum;
7455 LLT DstType = MRI.getType(DstReg);
7457 if (DstType.isVector())
7460 unsigned Opcode =
MI.getOpcode();
7461 unsigned OpO, OpE, OpF;
7463 case TargetOpcode::G_SADDO:
7464 case TargetOpcode::G_SADDE:
7465 case TargetOpcode::G_UADDO:
7466 case TargetOpcode::G_UADDE:
7467 case TargetOpcode::G_ADD:
7468 OpO = TargetOpcode::G_UADDO;
7469 OpE = TargetOpcode::G_UADDE;
7470 OpF = TargetOpcode::G_UADDE;
7471 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7472 OpF = TargetOpcode::G_SADDE;
7474 case TargetOpcode::G_SSUBO:
7475 case TargetOpcode::G_SSUBE:
7476 case TargetOpcode::G_USUBO:
7477 case TargetOpcode::G_USUBE:
7478 case TargetOpcode::G_SUB:
7479 OpO = TargetOpcode::G_USUBO;
7480 OpE = TargetOpcode::G_USUBE;
7481 OpF = TargetOpcode::G_USUBE;
7482 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7483 OpF = TargetOpcode::G_SSUBE;
7490 unsigned NumDefs =
MI.getNumExplicitDefs();
7491 Register Src1 =
MI.getOperand(NumDefs).getReg();
7492 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7495 CarryDst =
MI.getOperand(1).getReg();
7496 if (
MI.getNumOperands() == NumDefs + 3)
7497 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7499 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7500 LLT LeftoverTy, DummyTy;
7502 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7507 int NarrowParts = Src1Regs.
size();
7508 Src1Regs.
append(Src1Left);
7509 Src2Regs.
append(Src2Left);
7512 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7514 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7517 if (i == e - 1 && CarryDst)
7518 CarryOut = CarryDst;
7520 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7523 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7524 {Src1Regs[i], Src2Regs[i]});
7525 }
else if (i == e - 1) {
7526 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7527 {Src1Regs[i], Src2Regs[i], CarryIn});
7529 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7530 {Src1Regs[i], Src2Regs[i], CarryIn});
7536 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7537 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7538 ArrayRef(DstRegs).drop_front(NarrowParts));
7540 MI.eraseFromParent();
7546 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7548 LLT Ty = MRI.getType(DstReg);
7552 unsigned Size = Ty.getSizeInBits();
7554 if (
Size % NarrowSize != 0)
7558 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH ||
7559 MI.getOpcode() == TargetOpcode::G_SMULH;
7560 unsigned DstTmpParts =
NumParts * (IsMulHigh ? 2 : 1);
7566 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7571 if (
MI.getOpcode() == TargetOpcode::G_SMULH) {
7572 Register UnsignedHigh = MRI.createGenericVirtualRegister(Ty);
7573 MIRBuilder.buildMergeLikeInstr(UnsignedHigh, DstRegs);
7576 auto ShiftAmt =
MIRBuilder.buildConstant(NarrowTy, NarrowSize - 1);
7579 MIRBuilder.buildAShr(NarrowTy, Src1Parts.back(), ShiftAmt.getReg(0));
7581 MIRBuilder.buildAShr(NarrowTy, Src2Parts.back(), ShiftAmt.getReg(0));
7587 auto SignA =
MIRBuilder.buildMergeLikeInstr(Ty, SignAParts);
7588 auto SignB =
MIRBuilder.buildMergeLikeInstr(Ty, SignBParts);
7592 auto Ca =
MIRBuilder.buildAnd(Ty, SignA, Src2);
7593 auto Cb =
MIRBuilder.buildAnd(Ty, SignB, Src1);
7596 auto Tmp =
MIRBuilder.buildSub(Ty, UnsignedHigh, Ca);
7599 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7602 MI.eraseFromParent();
7612 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7615 LLT SrcTy = MRI.getType(Src);
7627 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7640 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7643 if (SizeOp1 % NarrowSize != 0)
7645 int NumParts = SizeOp1 / NarrowSize;
7652 uint64_t OpStart =
MI.getOperand(2).getImm();
7653 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7654 for (
int i = 0; i <
NumParts; ++i) {
7655 unsigned SrcStart = i * NarrowSize;
7657 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7660 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7668 int64_t ExtractOffset;
7670 if (OpStart < SrcStart) {
7672 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7674 ExtractOffset = OpStart - SrcStart;
7675 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7679 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7681 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7682 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7689 if (MRI.getType(DstReg).isVector())
7690 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7691 else if (DstRegs.
size() > 1)
7692 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7695 MI.eraseFromParent();
7707 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7709 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7712 SrcRegs.
append(LeftoverRegs);
7716 uint64_t OpStart =
MI.getOperand(3).getImm();
7717 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7718 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7719 unsigned DstStart =
I * NarrowSize;
7721 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7729 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7731 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7735 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7743 int64_t ExtractOffset, InsertOffset;
7745 if (OpStart < DstStart) {
7747 ExtractOffset = DstStart - OpStart;
7748 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7750 InsertOffset = OpStart - DstStart;
7752 SegSize = std::min(NarrowSize - InsertOffset, OpSize);
7756 if (ExtractOffset != 0 || SegSize != OpSize) {
7758 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7759 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7762 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7763 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7767 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7771 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7774 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7776 MI.eraseFromParent();
7784 LLT DstTy = MRI.getType(DstReg);
7786 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7792 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7793 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7797 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7798 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7801 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7802 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7803 {Src0Regs[I], Src1Regs[I]});
7807 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7810 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7811 DstLeftoverRegs.
push_back(Inst.getReg(0));
7814 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7815 LeftoverTy, DstLeftoverRegs);
7817 MI.eraseFromParent();
7827 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7829 LLT DstTy = MRI.getType(DstReg);
7834 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7835 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7836 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7838 MI.eraseFromParent();
7848 Register CondReg =
MI.getOperand(1).getReg();
7849 LLT CondTy = MRI.getType(CondReg);
7850 if (CondTy.isVector())
7854 LLT DstTy = MRI.getType(DstReg);
7860 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7861 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7865 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7866 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7869 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7871 CondReg, Src1Regs[
I], Src2Regs[
I]);
7875 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7877 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7881 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7882 LeftoverTy, DstLeftoverRegs);
7884 MI.eraseFromParent();
7894 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7897 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7898 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7901 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7903 auto C_0 =
B.buildConstant(NarrowTy, 0);
7905 UnmergeSrc.getReg(1), C_0);
7906 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7907 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7908 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7909 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7910 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7911 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7913 MI.eraseFromParent();
7926 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7929 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7930 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7933 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7935 auto C_0 =
B.buildConstant(NarrowTy, 0);
7937 UnmergeSrc.getReg(0), C_0);
7938 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7939 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7940 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7941 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7942 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7943 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7945 MI.eraseFromParent();
7958 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7961 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7966 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7970 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7971 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7979 auto LoInv =
B.buildXor(DstTy,
Lo,
Sign);
7980 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7983 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7984 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7986 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7988 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7990 MI.eraseFromParent();
8000 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8003 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
8004 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
8006 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
8007 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
8008 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
8010 MI.eraseFromParent();
8025 LLT ExpTy = MRI.getType(ExpReg);
8030 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
8031 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
8032 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
8033 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
8035 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
8037 MI.getOperand(2).setReg(Trunc.getReg(0));
8044 unsigned Opc =
MI.getOpcode();
8047 auto QAction = LI.getAction(Q).Action;
8053 case TargetOpcode::G_CTLZ_ZERO_POISON: {
8056 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
8060 case TargetOpcode::G_CTLZ: {
8061 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8062 unsigned Len = SrcTy.getScalarSizeInBits();
8064 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
8066 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
8067 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
8070 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8071 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
8072 MI.eraseFromParent();
8088 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
8089 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
8092 Op = MIBOp.getReg(0);
8097 MI.eraseFromParent();
8100 case TargetOpcode::G_CTTZ_ZERO_POISON: {
8103 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
8107 case TargetOpcode::G_CTTZ: {
8108 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8110 unsigned Len = SrcTy.getScalarSizeInBits();
8111 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
8114 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
8118 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8119 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
8120 MI.eraseFromParent();
8127 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8128 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8130 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8131 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8132 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8133 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8136 MI.eraseFromParent();
8140 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8141 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8145 case TargetOpcode::G_CTPOP: {
8147 LLT Ty = MRI.getType(SrcReg);
8148 unsigned Size = Ty.getScalarSizeInBits();
8160 auto C_1 =
B.buildConstant(Ty, 1);
8161 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8163 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8164 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8165 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8169 auto C_2 =
B.buildConstant(Ty, 2);
8170 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8172 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8173 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8174 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8175 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8182 auto C_4 =
B.buildConstant(Ty, 4);
8183 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8184 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8186 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8187 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8189 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8192 if (
Size == 16 && !Ty.isVector()) {
8194 auto C_8 =
B.buildConstant(Ty, 8);
8195 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8196 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8197 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8198 MI.eraseFromParent();
8207 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8209 auto IsMulSupported = [
this](
const LLT Ty) {
8210 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8213 if (IsMulSupported(Ty)) {
8214 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8215 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8217 auto ResTmp = B8Count;
8218 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8219 auto ShiftC =
B.buildConstant(Ty, Shift);
8220 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8221 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8223 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8225 MI.eraseFromParent();
8228 case TargetOpcode::G_CTLS: {
8229 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8233 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8234 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8236 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8242 MI.eraseFromParent();
8272 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8273 LLT Ty = MRI.getType(Dst);
8274 LLT ShTy = MRI.getType(Z);
8281 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8282 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8292 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8305 MI.eraseFromParent();
8311 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8312 LLT Ty = MRI.getType(Dst);
8313 LLT ShTy = MRI.getType(Z);
8316 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8330 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8331 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8332 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8333 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8334 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8340 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8343 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8346 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8348 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8349 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8350 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8353 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8355 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8357 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8360 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8361 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8366 MI.eraseFromParent();
8377 LLT Ty = MRI.getType(Dst);
8378 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8380 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8381 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8384 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8385 return lowerFunnelShiftAsShifts(
MI);
8389 if (Result == UnableToLegalize)
8390 return lowerFunnelShiftAsShifts(
MI);
8395 auto [Dst, Src] =
MI.getFirst2Regs();
8396 LLT DstTy = MRI.getType(Dst);
8397 LLT SrcTy = MRI.getType(Src);
8401 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8409 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8413 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8417 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8422 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8423 {UnmergeSrc.getReg(0)});
8424 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8425 {UnmergeSrc.getReg(1)});
8428 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8430 MI.eraseFromParent();
8447 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8451 LLT DstTy = MRI.getType(DstReg);
8452 LLT SrcTy = MRI.getType(SrcReg);
8460 SrcTy.getElementCount().divideCoefficientBy(2));
8473 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8485 MI.eraseFromParent();
8494 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8496 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8497 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8499 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8500 MI.eraseFromParent();
8505 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8507 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8508 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8513 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8514 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8516 return lowerRotateWithReverseRotate(
MI);
8519 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8520 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8521 bool IsFShLegal =
false;
8522 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8523 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8527 MI.eraseFromParent();
8532 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8535 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8540 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8541 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8542 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8554 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8556 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8563 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8564 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8566 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8568 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8572 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal, OrFlags);
8573 MI.eraseFromParent();
8581 auto [Dst, Src] =
MI.getFirst2Regs();
8586 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8599 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8601 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8606 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8608 MI.eraseFromParent();
8616 auto [Dst, Src] =
MI.getFirst2Regs();
8620 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8631 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8632 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8634 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8641 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8642 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8643 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8645 MI.eraseFromParent();
8656 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8657 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8663 MI.eraseFromParent();
8668 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8674 MI.eraseFromParent();
8678 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8698 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8708 MI.eraseFromParent();
8712 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8718 if (DstTy.getScalarSizeInBits() == 32) {
8725 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8726 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8728 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8735 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8736 MI.eraseFromParent();
8744 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8748 if (SrcTy !=
S64 && SrcTy !=
S32)
8750 if (DstTy !=
S32 && DstTy !=
S64)
8777 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8779 MI.eraseFromParent();
8784 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8789 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8796 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8798 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8799 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8801 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8802 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8804 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8806 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8807 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8808 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8811 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8812 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8813 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8815 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask,
K);
8818 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8823 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8824 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8830 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8835 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8840 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8841 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8843 MI.eraseFromParent();
8849 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8851 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8852 unsigned SatWidth = DstTy.getScalarSizeInBits();
8856 APInt MinInt, MaxInt;
8879 if (AreExactFloatBounds) {
8881 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8884 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8886 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8895 MI.eraseFromParent();
8900 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8905 MI.eraseFromParent();
8912 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8920 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8930 MI.eraseFromParent();
8936 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8940 MI.eraseFromParent();
8947 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8948 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8949 "Only G_FPEXT and G_FPTRUNC are expected");
8951 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8956 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8958 StoreOpc = TargetOpcode::G_STORE;
8959 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8962 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8963 LoadOpc = TargetOpcode::G_LOAD;
8972 StackTy, StackTyAlign);
8973 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8976 StackTy, StackTyAlign);
8977 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8979 MI.eraseFromParent();
8987 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8988 assert(SrcTy.getScalarType().isBFloat16() &&
8989 "expected a bf16 source for bf16 fpext lowering");
9000 if (DstTy.getScalarType().isFloat32())
9005 MI.eraseFromParent();
9010 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9011 if (SrcTy.getScalarType().isBFloat16() &&
9012 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
9024 auto [Dst, Src] =
MI.getFirst2Regs();
9028 if (MRI.getType(Src).isVector())
9032 unsigned Flags =
MI.getFlags();
9035 MI.eraseFromParent();
9039 const unsigned ExpMask = 0x7ff;
9040 const unsigned ExpBiasf64 = 1023;
9041 const unsigned ExpBiasf16 = 15;
9043 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
9053 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
9060 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
9064 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
9068 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
9070 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200,
Zero);
9072 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
9073 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
9081 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
9093 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9104 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9120 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9130 MI.eraseFromParent();
9137 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9145 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9171 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9173 MI.eraseFromParent();
9182 LLT OperandTy = MRI.getType(
Op);
9192 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9194 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9195 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9196 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9198 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9206 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9209 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9211 AbsWide, AbsNarrowAsWide);
9215 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9216 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9218 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9219 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9225 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9231 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9232 MI.eraseFromParent();
9238 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9239 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9242 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9245 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9252 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9253 LLT Ty = MRI.getType(Dst);
9255 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9256 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9257 MI.eraseFromParent();
9262 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9263 LLT Ty = MRI.getType(Src);
9264 auto Flags =
MI.getFlags();
9272 FracToUse = FracPart.getReg(0);
9274 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9280 FracToUse =
Select.getReg(0);
9283 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9286 MI.eraseFromParent();
9292 case TargetOpcode::G_SMIN:
9294 case TargetOpcode::G_SMAX:
9296 case TargetOpcode::G_UMIN:
9298 case TargetOpcode::G_UMAX:
9306 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9311 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9312 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9314 MI.eraseFromParent();
9323 LLT DstTy = MRI.getType(Dst);
9324 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9335 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9337 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9340 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9341 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9342 if (TLI.preferSelectsOverBooleanArithmetic(
9345 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9346 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One,
Zero);
9348 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9349 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9355 unsigned BoolExtOp =
9357 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9358 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9362 MI.eraseFromParent();
9368 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9369 const int Src0Size = Src0Ty.getScalarSizeInBits();
9370 const int Src1Size = Src1Ty.getScalarSizeInBits();
9380 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9381 Src0Ty.getScalarType().isInteger()))
9382 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9384 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9385 Src1Ty.getScalarType().isInteger()))
9386 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9391 auto NotSignBitMask =
MIRBuilder.buildConstant(
9395 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9397 if (Src0Ty == Src1Ty) {
9398 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9399 }
else if (Src0Size > Src1Size) {
9400 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9401 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9402 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9403 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9405 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9406 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9407 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9408 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9414 unsigned Flags =
MI.getFlags();
9419 if (DstTy == DstIntTy)
9420 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9426 MI.eraseFromParent();
9437 switch (
MI.getOpcode()) {
9438 case TargetOpcode::G_FMINNUM:
9439 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9441 case TargetOpcode::G_FMINIMUMNUM:
9442 NewOp = TargetOpcode::G_FMINNUM;
9444 case TargetOpcode::G_FMAXNUM:
9445 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9447 case TargetOpcode::G_FMAXIMUMNUM:
9448 NewOp = TargetOpcode::G_FMAXNUM;
9454 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9455 LLT Ty = MRI.getType(Dst);
9464 if (!VT->isKnownNeverSNaN(Src0))
9465 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9467 if (!VT->isKnownNeverSNaN(Src1))
9468 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9473 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9474 MI.eraseFromParent();
9480 unsigned Opc =
MI.getOpcode();
9481 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9482 LLT Ty = MRI.getType(Dst);
9485 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9487 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9488 unsigned OpcNonIeee =
9489 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9490 bool MinMaxMustRespectOrderedZero =
false;
9494 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9496 MinMaxMustRespectOrderedZero =
true;
9497 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9502 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9507 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9510 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9514 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9516 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9528 const unsigned Flags =
MI.getFlags();
9534 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9536 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9538 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9540 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9542 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9547 MI.eraseFromParent();
9554 LLT Ty = MRI.getType(DstReg);
9555 unsigned Flags =
MI.getFlags();
9560 MI.eraseFromParent();
9566 auto [DstReg,
X] =
MI.getFirst2Regs();
9567 const unsigned Flags =
MI.getFlags();
9568 const LLT Ty = MRI.getType(DstReg);
9580 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9582 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9587 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9590 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9592 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9594 MI.eraseFromParent();
9599 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9600 unsigned Flags =
MI.getFlags();
9601 LLT Ty = MRI.getType(DstReg);
9608 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9612 SrcReg,
Zero, Flags);
9614 SrcReg, Trunc, Flags);
9618 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9619 MI.eraseFromParent();
9625 const unsigned NumOps =
MI.getNumOperands();
9626 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9627 unsigned PartSize = Src0Ty.getSizeInBits();
9632 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9633 const unsigned Offset = (
I - 1) * PartSize;
9636 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9639 MRI.createGenericVirtualRegister(WideTy);
9642 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9643 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9644 ResultReg = NextResult;
9647 if (DstTy.isPointer()) {
9648 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9649 DstTy.getAddressSpace())) {
9655 }
else if (WideTy != DstTy) {
9659 MI.eraseFromParent();
9665 const unsigned NumDst =
MI.getNumOperands() - 1;
9666 Register SrcReg =
MI.getOperand(NumDst).getReg();
9667 Register Dst0Reg =
MI.getOperand(0).getReg();
9668 LLT DstTy = MRI.getType(Dst0Reg);
9677 LLT IntTy = MRI.getType(SrcReg);
9682 unsigned Offset = DstSize;
9683 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9685 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9689 MI.eraseFromParent();
9708 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9709 InsertVal =
MI.getOperand(2).getReg();
9711 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9713 LLT VecTy = MRI.getType(SrcVec);
9723 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9724 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9726 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9729 MI.eraseFromParent();
9734 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9745 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9752 int64_t
Offset = IdxVal * EltBytes;
9763 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9766 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9768 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9771 MI.eraseFromParent();
9777 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9778 MI.getFirst3RegLLTs();
9788 for (
int Idx : Mask) {
9790 if (!
Undef.isValid())
9796 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9798 int NumElts = Src0Ty.getNumElements();
9799 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9800 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9801 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9803 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9805 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9810 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9811 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9812 MI.eraseFromParent();
9818 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9819 MI.getFirst4RegLLTs();
9821 if (VecTy.isScalableVector())
9837 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9842 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9845 std::optional<APInt> PassthruSplatVal =
9848 if (PassthruSplatVal.has_value()) {
9850 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9851 }
else if (HasPassthru) {
9852 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9853 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9859 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9863 unsigned NumElmts = VecTy.getNumElements();
9864 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9866 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9869 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9872 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9877 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9879 if (HasPassthru &&
I == NumElmts - 1) {
9882 auto AllLanesSelected =
MIRBuilder.buildICmp(
9884 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9885 {OutPos, EndOfVector});
9889 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9891 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9896 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9898 MI.eraseFromParent();
9915 if (Alignment >
Align(1)) {
9916 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9927 const auto &MF = *
MI.getMF();
9933 Register AllocSize =
MI.getOperand(1).getReg();
9936 LLT PtrTy = MRI.getType(Dst);
9937 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9944 MI.eraseFromParent();
9950 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9955 MI.eraseFromParent();
9961 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9966 MI.eraseFromParent();
9972 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9973 unsigned Offset =
MI.getOperand(2).getImm();
9976 if (SrcTy.isVector()) {
9977 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9978 unsigned DstSize = DstTy.getSizeInBits();
9980 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9981 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9983 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9987 for (
unsigned Idx =
Offset / SrcEltSize;
9988 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9989 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9991 if (SubVectorElts.
size() == 1)
9992 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9994 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9996 MI.eraseFromParent();
10002 if ((SrcTy.isPointer() &&
10003 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
10004 (DstTy.isPointer() &&
10005 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
10006 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10010 if ((DstTy.isScalar() || DstTy.isPointer()) &&
10011 (SrcTy.isScalar() || SrcTy.isPointer() ||
10012 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
10013 LLT SrcIntTy = SrcTy;
10014 if (!SrcTy.isScalar()) {
10016 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
10020 if (DstTy.isPointer())
10022 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
10028 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
10032 if (DstTy.isPointer())
10033 MIRBuilder.buildIntToPtr(DstReg, ResultReg);
10035 MI.eraseFromParent();
10043 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
10044 uint64_t
Offset =
MI.getOperand(3).getImm();
10046 LLT DstTy = MRI.getType(Src);
10047 LLT InsertTy = MRI.getType(InsertSrc);
10050 bool IsNonIntegralInsert =
10060 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
10061 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10068 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
10070 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
10074 for (; Idx <
Offset / EltSize; ++Idx) {
10075 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10080 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
10081 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
10083 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
10087 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
10089 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
10096 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10099 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
10100 MI.eraseFromParent();
10109 if (IsNonIntegralDst || IsNonIntegralInsert) {
10110 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10114 LLT IntDstTy = DstTy;
10118 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
10123 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
10129 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10135 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10136 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10137 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10140 MI.eraseFromParent();
10146 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10147 MI.getFirst4RegLLTs();
10148 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10151 LLT BoolTy = Dst1Ty;
10153 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10168 auto ResultLowerThanLHS =
10172 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10176 auto LHSLessThanRHS =
10178 auto ResultNegative =
10180 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10184 MI.eraseFromParent();
10190 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10191 const LLT Ty = MRI.getType(Res);
10194 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10195 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10196 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10200 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10201 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10207 MI.eraseFromParent();
10212 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10213 const LLT Ty = MRI.getType(Res);
10216 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10217 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10218 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10222 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10223 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10228 MI.eraseFromParent();
10234 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10235 LLT Ty = MRI.getType(Res);
10239 switch (
MI.getOpcode()) {
10242 case TargetOpcode::G_UADDSAT:
10245 BaseOp = TargetOpcode::G_ADD;
10247 case TargetOpcode::G_SADDSAT:
10250 BaseOp = TargetOpcode::G_ADD;
10252 case TargetOpcode::G_USUBSAT:
10255 BaseOp = TargetOpcode::G_SUB;
10257 case TargetOpcode::G_SSUBSAT:
10260 BaseOp = TargetOpcode::G_SUB;
10275 uint64_t NumBits = Ty.getScalarSizeInBits();
10286 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10294 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10299 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10300 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10303 MI.eraseFromParent();
10309 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10310 LLT Ty = MRI.getType(Res);
10314 unsigned OverflowOp;
10315 switch (
MI.getOpcode()) {
10318 case TargetOpcode::G_UADDSAT:
10321 OverflowOp = TargetOpcode::G_UADDO;
10323 case TargetOpcode::G_SADDSAT:
10326 OverflowOp = TargetOpcode::G_SADDO;
10328 case TargetOpcode::G_USUBSAT:
10331 OverflowOp = TargetOpcode::G_USUBO;
10333 case TargetOpcode::G_SSUBSAT:
10336 OverflowOp = TargetOpcode::G_SSUBO;
10341 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10342 Register Tmp = OverflowRes.getReg(0);
10343 Register Ov = OverflowRes.getReg(1);
10352 uint64_t NumBits = Ty.getScalarSizeInBits();
10353 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10365 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10367 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10369 MI.eraseFromParent();
10375 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10376 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10377 "Expected shlsat opcode!");
10378 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10379 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10380 LLT Ty = MRI.getType(Res);
10384 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10385 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10394 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10399 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10401 MI.eraseFromParent();
10407 unsigned Opc =
MI.getOpcode();
10408 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10409 unsigned DstSize = DstTy.getScalarSizeInBits();
10410 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10412 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10415 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10418 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10419 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10422 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10423 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10426 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10428 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10434 MI.eraseFromParent();
10439 auto [Dst, Src] =
MI.getFirst2Regs();
10440 const LLT Ty = MRI.getType(Src);
10441 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10442 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10445 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10446 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10447 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10448 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10451 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10454 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10455 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10457 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10458 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10459 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10461 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10462 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10463 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10465 Res.getInstr()->getOperand(0).setReg(Dst);
10467 MI.eraseFromParent();
10474 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10477 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10478 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10479 return B.buildOr(Dst,
LHS,
RHS);
10484 auto [Dst, Src] =
MI.getFirst2Regs();
10485 const LLT SrcTy = MRI.getType(Src);
10486 unsigned Size = SrcTy.getScalarSizeInBits();
10487 unsigned VSize = SrcTy.getSizeInBits();
10490 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10491 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10492 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10493 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10498 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10499 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10500 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10504 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10527 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10531 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10534 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10538 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10542 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10547 MI.eraseFromParent();
10555 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10556 int NameOpIdx = IsRead ? 1 : 0;
10557 int ValRegIndex = IsRead ? 0 : 1;
10559 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10560 const LLT Ty = MRI.getType(ValReg);
10562 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10569 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10570 Fn,
MI.getDebugLoc()));
10574 MI.eraseFromParent();
10583 MI.eraseFromParent();
10589 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10590 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10591 Register Result =
MI.getOperand(0).getReg();
10592 LLT OrigTy = MRI.getType(Result);
10596 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10597 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10599 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10601 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10602 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10605 MI.eraseFromParent();
10611 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10616 MI.eraseFromParent();
10621 MI.eraseFromParent();
10628 unsigned BitSize = SrcTy.getScalarSizeInBits();
10632 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10639 APInt ExpMask = Inf;
10641 APInt QNaNBitMask =
10645 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10646 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10647 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10648 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10649 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10651 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10655 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10657 LLT DstTyCopy = DstTy;
10659 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10687 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10690 Mask &= ~PartialCheck;
10699 else if (PartialCheck ==
fcZero)
10711 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10712 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10713 auto SubnormalRes =
10715 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10718 appendToRes(SubnormalRes);
10725 else if (PartialCheck ==
fcInf)
10730 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10737 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10738 if (PartialCheck ==
fcNan) {
10742 }
else if (PartialCheck ==
fcQNan) {
10752 Abs, InfWithQnanBitC);
10753 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10760 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10762 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10763 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10766 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10772 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10774 appendToRes(NormalRes);
10778 MI.eraseFromParent();
10784 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10785 MI.getFirst4RegLLTs();
10794 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10795 Op1Ty = MRI.getType(Op1Reg);
10796 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10797 Op2Ty = MRI.getType(Op2Reg);
10801 if (MaskTy.isScalar()) {
10809 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10812 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10814 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10816 if (DstTy.isVector()) {
10818 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10819 MaskReg = ShufSplat.getReg(0);
10823 }
else if (!DstTy.isVector()) {
10828 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10832 if (!Op1Ty.getScalarType().isAnyScalar() &&
10833 !Op1Ty.getScalarType().isInteger())
10834 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10836 if (!Op2Ty.getScalarType().isAnyScalar() &&
10837 !Op2Ty.getScalarType().isInteger()) {
10839 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10840 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10843 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10844 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10845 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10850 if (DstTy == Op1TyInt)
10853 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10857 MI.eraseFromParent();
10863 unsigned Opcode =
MI.getOpcode();
10866 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10867 : TargetOpcode::G_UDIV,
10868 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10870 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10871 : TargetOpcode::G_UREM,
10872 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10873 MI.eraseFromParent();
10883 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10887 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10890 MI.eraseFromParent();
10900 Register SrcReg =
MI.getOperand(1).getReg();
10901 LLT Ty = MRI.getType(SrcReg);
10905 MI.eraseFromParent();
10911 Register SrcReg =
MI.getOperand(1).getReg();
10912 Register DestReg =
MI.getOperand(0).getReg();
10918 MI.eraseFromParent();
10924 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10925 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10926 "Expected G_ABDS or G_ABDU instruction");
10928 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10929 LLT Ty = MRI.getType(LHS);
10939 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10941 MI.eraseFromParent();
10947 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10948 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10949 "Expected G_ABDS or G_ABDU instruction");
10951 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10952 LLT Ty = MRI.getType(LHS);
10957 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10958 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10959 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10961 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10962 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10964 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10966 MI.eraseFromParent();
10971 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10976 if (!(SrcTy.getScalarType().isAnyScalar() ||
10977 SrcTy.getScalarType().isInteger())) {
10979 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10980 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10983 if (MRI.getType(DstReg) != TyInt) {
10987 .buildAnd(TyInt, CastedSrc,
10990 DstTy.getScalarSizeInBits())))
11002 MI.eraseFromParent();
11008 Register SrcReg =
MI.getOperand(1).getReg();
11009 LLT SrcTy = MRI.getType(SrcReg);
11010 LLT DstTy = MRI.getType(SrcReg);
11013 if (SrcTy.isScalar()) {
11018 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
11029 Register ListPtr =
MI.getOperand(1).getReg();
11030 LLT PtrTy = MRI.getType(ListPtr);
11037 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
11039 const Align A(
MI.getOperand(2).getImm());
11041 if (
A > TLI.getMinStackArgumentAlignment()) {
11043 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
11044 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
11045 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
11046 VAList = AndDst.getReg(0);
11053 LLT LLTTy = MRI.getType(Dst);
11056 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
11057 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
11062 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
11064 Align EltAlignment =
DL.getABITypeAlign(Ty);
11067 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
11069 MI.eraseFromParent();
11074 unsigned OpCode =
MI.getOpcode();
11075 assert((OpCode == TargetOpcode::G_SMULFIX ||
11076 OpCode == TargetOpcode::G_UMULFIX ||
11077 OpCode == TargetOpcode::G_SMULFIXSAT ||
11078 OpCode == TargetOpcode::G_UMULFIXSAT) &&
11079 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
11080 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
11081 LLT Ty = MRI.getType(Dst);
11082 unsigned Scale =
MI.getOperand(3).getImm();
11084 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
11085 OpCode == TargetOpcode::G_UMULFIXSAT);
11086 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
11087 OpCode == TargetOpcode::G_SMULFIXSAT);
11089 if (!Saturating && Scale == 0) {
11091 MI.eraseFromParent();
11097 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
11120 MI.eraseFromParent();
11127 unsigned NumBits = Ty.getScalarSizeInBits();
11129 if (!Ty.isVector() && ValVRegAndVal) {
11130 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
11138 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11161 auto &MF = *
MI.getParent()->getParent();
11166 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11167 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11170 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11171 const auto &DstMMO = **
MI.memoperands_begin();
11173 if (DstAlignCanChange) {
11176 Align NewAlign =
DL.getABITypeAlign(IRTy);
11177 if (NewAlign > Alignment) {
11186 MachineIRBuilder MIB(
MI);
11188 LLT LargestTy = MemOps[0];
11189 for (
unsigned i = 1; i < MemOps.
size(); i++)
11191 LargestTy = MemOps[i];
11203 LLT PtrTy = MRI.getType(Dst);
11204 unsigned DstOff = 0;
11205 unsigned Size = KnownLen;
11206 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11207 LLT Ty = MemOps[
I];
11210 if (TySize >
Size) {
11214 DstOff -= TySize -
Size;
11224 TLI.isTruncateFree(LargestVT, VT))
11225 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11238 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11241 MIB.buildStore(
Value, Ptr, *StoreMMO);
11246 MI.eraseFromParent();
11254 auto &MF = *
MI.getParent()->getParent();
11258 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11259 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11262 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11268 const auto &DstMMO = **
MI.memoperands_begin();
11269 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11271 if (DstAlignCanChange) {
11274 Align NewAlign =
DL.getABITypeAlign(IRTy);
11279 if (!
TRI->hasStackRealignment(MF))
11280 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11281 NewAlign = std::min(NewAlign, *StackAlign);
11283 if (NewAlign > Alignment) {
11292 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11294 MachineIRBuilder MIB(
MI);
11300 LLT SrcTy = MRI.getType(Src);
11301 LLT DstTy = MRI.getType(Dst);
11304 unsigned CurrOffset = 0;
11305 unsigned Size = KnownLen;
11306 for (
auto CopyTy : MemOps) {
11307 TypeSize TySize = CopyTy.getSizeInBytes();
11311 if (TySize >
Size) {
11312 unsigned Overlap = TySize -
Size;
11313 assert(Overlap < CurrOffset &&
11314 "overlapping memcpy load/store spans the whole region or more");
11315 CurrOffset -= Overlap;
11325 if (CurrOffset != 0) {
11327 MIB.buildConstant(
LLT::integer(SrcIndexSize), CurrOffset).getReg(0);
11328 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11330 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11334 if (CurrOffset != 0) {
11335 if (SrcIndexSize != DstIndexSize) {
11337 MIB.buildConstant(
LLT::integer(DstIndexSize), CurrOffset).getReg(0);
11339 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11341 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11342 CurrOffset += TySize;
11346 MI.eraseFromParent();
11354 auto &MF = *
MI.getParent()->getParent();
11358 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11359 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11362 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11363 const auto &DstMMO = **
MI.memoperands_begin();
11364 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11366 if (DstAlignCanChange) {
11369 Align NewAlign =
DL.getABITypeAlign(IRTy);
11374 if (!
TRI->hasStackRealignment(MF))
11375 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11376 NewAlign = std::min(NewAlign, *StackAlign);
11378 if (NewAlign > Alignment) {
11387 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11389 MachineIRBuilder MIB(
MI);
11393 unsigned CurrOffset = 0;
11394 unsigned Size = KnownLen;
11395 SmallVector<Register, 16> LoadVals;
11396 for (
auto CopyTy : MemOps) {
11397 TypeSize TySize = CopyTy.getSizeInBytes();
11401 if (TySize >
Size) {
11402 unsigned Overlap = TySize -
Size;
11403 assert(Overlap < CurrOffset &&
11404 "overlapping memmove load spans the whole region or more");
11405 CurrOffset -= Overlap;
11413 if (CurrOffset != 0) {
11414 LLT SrcTy = MRI.getType(Src);
11417 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11419 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11420 CurrOffset += TySize;
11426 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11427 LLT CopyTy = MemOps[
I];
11432 if (TySize >
Size) {
11433 unsigned Overlap = TySize -
Size;
11434 assert(Overlap < CurrOffset &&
11435 "overlapping memmove store spans the whole region or more");
11436 CurrOffset -= Overlap;
11443 if (CurrOffset != 0) {
11444 LLT DstTy = MRI.getType(Dst);
11447 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11449 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11450 CurrOffset += TySize;
11453 MI.eraseFromParent();
11460 const unsigned Opc =
MI.getOpcode();
11461 assert((
Opc == TargetOpcode::G_MEMCPY ||
11462 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11463 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11464 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11465 "Expected memcpy like instruction");
11467 if (KnownLen == 0) {
11468 MI.eraseFromParent();
11472 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11473 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11476 if (
Opc == TargetOpcode::G_MEMMOVE)
11477 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11479 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11480 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11490 bool DstAlignCanChange;
11491 std::vector<LLT> MemOps;
11493 DstAlignCanChange, MemOps))
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static bool isNonZeroModBitWidth(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
static bool hasSwiftErrorArg(MachineFunction &MF)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static MachineBasicBlock::iterator getPHIIncomingInsertPoint(MachineBasicBlock &MBB, Register Reg, const MachineRegisterInfo &MRI)
Choose an insertion point for a conversion of an incoming PHI value.
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.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Helper class to build MachineInstr.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_UREM Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0)
Build and insert integer negation Zero = G_CONSTANT 0 Res = G_SUB Zero, Op0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_UITOFP Src0.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
Represent a constant reference to a string, i.e.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
@ Bitcast
Build the immediate as a bitcast of an integer constant with the same bits.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Type * getType() const
All values are typed, get the type of this value.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
ImplicitDefMatch m_GImplicitDef()
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(Register Def, const MachineRegisterInfo &MRI)
Determines if Def defines a constant integer or a splat vector of constant integers.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, llvm::function_ref< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
LLVM_ABI bool canLowerMemCpyFamily(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned MaxLen, Register &Dst, Register &Src, uint64_t &KnownLen, Align &Alignment, bool &DstAlignCanChange, std::vector< LLT > &MemOps)
Matcher for memcpy-like instructions.
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.