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());
923 case TargetOpcode::G_ATOMIC_CMPXCHG:
924 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
926 case TargetOpcode::G_ATOMICRMW_XCHG:
928 case TargetOpcode::G_ATOMICRMW_ADD:
929 case TargetOpcode::G_ATOMICRMW_SUB:
931 case TargetOpcode::G_ATOMICRMW_AND:
933 case TargetOpcode::G_ATOMICRMW_OR:
935 case TargetOpcode::G_ATOMICRMW_XOR:
945 unsigned Opc =
MI.getOpcode();
958 if (LC.
Impl == RTLIB::Unsupported) {
972 case TargetOpcode::G_ATOMIC_CMPXCHG:
973 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
976 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
977 MI.getFirst4RegLLTs();
980 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
981 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
982 NewLLT) =
MI.getFirst5RegLLTs();
992 case TargetOpcode::G_ATOMICRMW_XCHG:
993 case TargetOpcode::G_ATOMICRMW_ADD:
994 case TargetOpcode::G_ATOMICRMW_SUB:
995 case TargetOpcode::G_ATOMICRMW_AND:
996 case TargetOpcode::G_ATOMICRMW_OR:
997 case TargetOpcode::G_ATOMICRMW_XOR: {
998 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
1001 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
1005 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
1017 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
1019 Info.
CallConv = Libcalls->getLibcallImplCallingConv(LC.
Impl);
1033static RTLIB::Libcall
1035 RTLIB::Libcall RTLibcall;
1036 switch (
MI.getOpcode()) {
1037 case TargetOpcode::G_GET_FPENV:
1038 RTLibcall = RTLIB::FEGETENV;
1040 case TargetOpcode::G_SET_FPENV:
1041 case TargetOpcode::G_RESET_FPENV:
1042 RTLibcall = RTLIB::FESETENV;
1044 case TargetOpcode::G_GET_FPMODE:
1045 RTLibcall = RTLIB::FEGETMODE;
1047 case TargetOpcode::G_SET_FPMODE:
1048 case TargetOpcode::G_RESET_FPMODE:
1049 RTLibcall = RTLIB::FESETMODE;
1081 LLT StateTy = MRI.getType(Dst);
1084 MachinePointerInfo TempPtrInfo;
1088 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1093 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
1101 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1119 LLT StateTy = MRI.getType(Src);
1122 MachinePointerInfo TempPtrInfo;
1131 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1136 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1137 LocObserver,
nullptr);
1143static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1145#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1149 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1151 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1153 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1155 llvm_unreachable("unexpected size"); \
1188 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1191 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1198 LLT DstTy = MRI.getType(DstReg);
1199 const auto Cond =
Cmp->getCond();
1200 Type *RetTy = TLI.getCmpLibcallReturnType(Ctx);
1205 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1210 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1214 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1221 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1227 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1229 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1242 const auto [OeqLibcall, OeqPred] =
1244 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1246 const auto [UnoLibcall, UnoPred] =
1248 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1263 const auto [OeqLibcall, OeqPred] =
1268 const auto [UnoLibcall, UnoPred] =
1273 if (NotOeq && NotUno)
1292 const auto [InversedLibcall, InversedPred] =
1294 if (!BuildLibcall(InversedLibcall,
1319 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1321 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1324 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1330 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1335 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1337 switch (
MI.getOpcode()) {
1340 case TargetOpcode::G_MUL:
1341 case TargetOpcode::G_SDIV:
1342 case TargetOpcode::G_UDIV:
1343 case TargetOpcode::G_SREM:
1344 case TargetOpcode::G_UREM:
1345 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1346 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1354 case TargetOpcode::G_FADD:
1355 case TargetOpcode::G_FSUB:
1356 case TargetOpcode::G_FMUL:
1357 case TargetOpcode::G_FDIV:
1358 case TargetOpcode::G_FMA:
1359 case TargetOpcode::G_FPOW:
1360 case TargetOpcode::G_FREM:
1361 case TargetOpcode::G_FCOS:
1362 case TargetOpcode::G_FSIN:
1363 case TargetOpcode::G_FTAN:
1364 case TargetOpcode::G_FACOS:
1365 case TargetOpcode::G_FASIN:
1366 case TargetOpcode::G_FATAN:
1367 case TargetOpcode::G_FATAN2:
1368 case TargetOpcode::G_FCOSH:
1369 case TargetOpcode::G_FSINH:
1370 case TargetOpcode::G_FTANH:
1371 case TargetOpcode::G_FLOG10:
1372 case TargetOpcode::G_FLOG:
1373 case TargetOpcode::G_FLOG2:
1374 case TargetOpcode::G_FEXP:
1375 case TargetOpcode::G_FEXP2:
1376 case TargetOpcode::G_FEXP10:
1377 case TargetOpcode::G_FCEIL:
1378 case TargetOpcode::G_FFLOOR:
1379 case TargetOpcode::G_FMINNUM:
1380 case TargetOpcode::G_FMAXNUM:
1381 case TargetOpcode::G_FMINIMUMNUM:
1382 case TargetOpcode::G_FMAXIMUMNUM:
1383 case TargetOpcode::G_FSQRT:
1384 case TargetOpcode::G_FRINT:
1385 case TargetOpcode::G_FNEARBYINT:
1386 case TargetOpcode::G_INTRINSIC_TRUNC:
1387 case TargetOpcode::G_INTRINSIC_ROUND:
1388 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1389 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1393 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1401 case TargetOpcode::G_FSINCOS: {
1402 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1406 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1411 case TargetOpcode::G_FMODF: {
1412 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1416 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1421 case TargetOpcode::G_LROUND:
1422 case TargetOpcode::G_LLROUND:
1423 case TargetOpcode::G_INTRINSIC_LRINT:
1424 case TargetOpcode::G_INTRINSIC_LLRINT: {
1425 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1429 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1431 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1437 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1440 MI.eraseFromParent();
1443 case TargetOpcode::G_FPOWI:
1444 case TargetOpcode::G_FLDEXP: {
1445 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1449 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1451 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1456 {
MI.getOperand(1).getReg(), HLTy, 0},
1457 {
MI.getOperand(2).getReg(), ITy, 1}};
1458 Args[1].Flags[0].setSExt();
1460 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1465 case TargetOpcode::G_FPEXT:
1466 case TargetOpcode::G_FPTRUNC: {
1469 if (!FromTy || !ToTy)
1476 case TargetOpcode::G_FCMP: {
1480 MI.eraseFromParent();
1483 case TargetOpcode::G_FPTOSI:
1484 case TargetOpcode::G_FPTOUI: {
1488 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1489 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1492 FromTy, LocObserver);
1497 case TargetOpcode::G_SITOFP:
1498 case TargetOpcode::G_UITOFP: {
1499 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1502 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1504 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1511 case TargetOpcode::G_ATOMICRMW_XCHG:
1512 case TargetOpcode::G_ATOMICRMW_ADD:
1513 case TargetOpcode::G_ATOMICRMW_SUB:
1514 case TargetOpcode::G_ATOMICRMW_AND:
1515 case TargetOpcode::G_ATOMICRMW_OR:
1516 case TargetOpcode::G_ATOMICRMW_XOR:
1517 case TargetOpcode::G_ATOMIC_CMPXCHG:
1518 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1524 case TargetOpcode::G_BZERO:
1525 case TargetOpcode::G_MEMCPY:
1526 case TargetOpcode::G_MEMMOVE:
1527 case TargetOpcode::G_MEMSET: {
1532 MI.eraseFromParent();
1535 case TargetOpcode::G_GET_FPENV:
1536 case TargetOpcode::G_GET_FPMODE: {
1542 case TargetOpcode::G_SET_FPENV:
1543 case TargetOpcode::G_SET_FPMODE: {
1549 case TargetOpcode::G_RESET_FPENV:
1550 case TargetOpcode::G_RESET_FPMODE: {
1558 MI.eraseFromParent();
1565 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1568 switch (
MI.getOpcode()) {
1571 case TargetOpcode::G_IMPLICIT_DEF: {
1573 LLT DstTy = MRI.getType(DstReg);
1581 if (SizeOp0 % NarrowSize != 0) {
1586 MI.eraseFromParent();
1590 int NumParts = SizeOp0 / NarrowSize;
1597 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1599 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1600 MI.eraseFromParent();
1603 case TargetOpcode::G_CONSTANT: {
1604 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1605 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1606 unsigned TotalSize = Ty.getSizeInBits();
1608 int NumParts = TotalSize / NarrowSize;
1612 unsigned Offset =
I * NarrowSize;
1619 unsigned LeftoverBits = TotalSize -
NumParts * NarrowSize;
1621 if (LeftoverBits != 0) {
1629 insertParts(
MI.getOperand(0).getReg(),
1630 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1632 MI.eraseFromParent();
1635 case TargetOpcode::G_BITCAST: {
1636 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
1637 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1638 if (SrcTy.isVector() || DstTy.
isVector())
1641 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1642 unsigned NumParts = Unmerge->getNumOperands() - 1;
1645 Parts[
I] = Unmerge.getReg(
I);
1647 MI.eraseFromParent();
1650 case TargetOpcode::G_SEXT:
1651 case TargetOpcode::G_ZEXT:
1652 case TargetOpcode::G_ANYEXT:
1654 case TargetOpcode::G_TRUNC: {
1658 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1660 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1664 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1665 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1666 MI.eraseFromParent();
1669 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1670 case TargetOpcode::G_FREEZE: {
1674 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1679 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1681 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1683 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1687 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1688 MI.eraseFromParent();
1691 case TargetOpcode::G_ADD:
1692 case TargetOpcode::G_SUB:
1693 case TargetOpcode::G_SADDO:
1694 case TargetOpcode::G_SSUBO:
1695 case TargetOpcode::G_SADDE:
1696 case TargetOpcode::G_SSUBE:
1697 case TargetOpcode::G_UADDO:
1698 case TargetOpcode::G_USUBO:
1699 case TargetOpcode::G_UADDE:
1700 case TargetOpcode::G_USUBE:
1702 case TargetOpcode::G_MUL:
1703 case TargetOpcode::G_UMULH:
1704 case TargetOpcode::G_SMULH:
1706 case TargetOpcode::G_EXTRACT:
1708 case TargetOpcode::G_INSERT:
1710 case TargetOpcode::G_LOAD: {
1712 Register DstReg = LoadMI.getDstReg();
1713 LLT DstTy = MRI.getType(DstReg);
1717 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1718 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1719 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1721 LoadMI.eraseFromParent();
1727 case TargetOpcode::G_ZEXTLOAD:
1728 case TargetOpcode::G_SEXTLOAD:
1729 case TargetOpcode::G_FPEXTLOAD: {
1731 Register DstReg = LoadMI.getDstReg();
1732 Register PtrReg = LoadMI.getPointerReg();
1734 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1735 auto &MMO = LoadMI.getMMO();
1738 if (MemSize == NarrowSize) {
1740 }
else if (MemSize < NarrowSize) {
1741 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1742 }
else if (MemSize > NarrowSize) {
1754 LoadMI.eraseFromParent();
1757 case TargetOpcode::G_STORE: {
1760 Register SrcReg = StoreMI.getValueReg();
1761 LLT SrcTy = MRI.getType(SrcReg);
1762 if (SrcTy.isVector())
1765 int NumParts = SizeOp0 / NarrowSize;
1767 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1768 if (SrcTy.isVector() && LeftoverBits != 0)
1771 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1772 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1774 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1775 StoreMI.eraseFromParent();
1781 case TargetOpcode::G_FPTRUNCSTORE: {
1783 Register SrcReg = StoreMI.getValueReg();
1784 Register PtrReg = StoreMI.getPointerReg();
1786 auto &MMO = StoreMI.getMMO();
1788 if (MemSize > NarrowSize) {
1792 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1793 if (MemSize == NarrowSize) {
1795 }
else if (MemSize < NarrowSize) {
1796 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1800 StoreMI.eraseFromParent();
1803 case TargetOpcode::G_SELECT:
1805 case TargetOpcode::G_AND:
1806 case TargetOpcode::G_OR:
1807 case TargetOpcode::G_XOR: {
1819 case TargetOpcode::G_SHL:
1820 case TargetOpcode::G_LSHR:
1821 case TargetOpcode::G_ASHR:
1823 case TargetOpcode::G_CTLZ:
1824 case TargetOpcode::G_CTLZ_ZERO_POISON:
1825 case TargetOpcode::G_CTTZ:
1826 case TargetOpcode::G_CTTZ_ZERO_POISON:
1827 case TargetOpcode::G_CTLS:
1828 case TargetOpcode::G_CTPOP:
1830 switch (
MI.getOpcode()) {
1831 case TargetOpcode::G_CTLZ:
1832 case TargetOpcode::G_CTLZ_ZERO_POISON:
1834 case TargetOpcode::G_CTTZ:
1835 case TargetOpcode::G_CTTZ_ZERO_POISON:
1837 case TargetOpcode::G_CTPOP:
1839 case TargetOpcode::G_CTLS:
1849 case TargetOpcode::G_INTTOPTR:
1857 case TargetOpcode::G_PTRTOINT:
1865 case TargetOpcode::G_PHI: {
1868 if (SizeOp0 % NarrowSize != 0)
1871 unsigned NumParts = SizeOp0 / NarrowSize;
1875 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1878 OpMBB,
MI.getOperand(i).getReg(), MRI));
1884 for (
unsigned i = 0; i <
NumParts; ++i) {
1885 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1887 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1888 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1889 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1892 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1894 MI.eraseFromParent();
1897 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1898 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1902 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1908 case TargetOpcode::G_ICMP: {
1910 LLT SrcTy = MRI.getType(LHS);
1916 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1922 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1923 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1929 LLT ResTy = MRI.getType(Dst);
1936 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1937 auto LHS = std::get<0>(LHSAndRHS);
1938 auto RHS = std::get<1>(LHSAndRHS);
1939 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1946 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1947 auto LHS = std::get<0>(LHSAndRHS);
1948 auto RHS = std::get<1>(LHSAndRHS);
1949 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1950 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1951 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1952 TargetOpcode::G_ZEXT);
1959 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1960 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1961 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1966 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1970 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1975 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1979 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1982 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1985 LHSPartRegs[
I], RHSPartRegs[
I]);
1986 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1992 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
2001 CmpOut = MRI.createGenericVirtualRegister(ResTy);
2005 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
2006 RHSLeftoverRegs[
I]);
2008 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
2009 RHSLeftoverRegs[
I]);
2012 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
2013 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
2019 MI.eraseFromParent();
2022 case TargetOpcode::G_FCMP:
2031 case TargetOpcode::G_SEXT_INREG: {
2035 int64_t SizeInBits =
MI.getOperand(2).getImm();
2044 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2045 MO1.
setReg(TruncMIB.getReg(0));
2048 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2060 if (SizeOp0 % NarrowSize != 0)
2062 int NumParts = SizeOp0 / NarrowSize;
2070 for (
int i = 0; i <
NumParts; ++i) {
2071 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2086 for (
int i = 0; i <
NumParts; ++i) {
2089 PartialExtensionReg = DstRegs.
back();
2091 assert(PartialExtensionReg &&
2092 "Expected to visit partial extension before full");
2093 if (FullExtensionReg) {
2098 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2100 FullExtensionReg = DstRegs.
back();
2105 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2108 PartialExtensionReg = DstRegs.
back();
2114 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2115 MI.eraseFromParent();
2118 case TargetOpcode::G_BSWAP:
2119 case TargetOpcode::G_BITREVERSE: {
2120 if (SizeOp0 % NarrowSize != 0)
2125 unsigned NumParts = SizeOp0 / NarrowSize;
2129 for (
unsigned i = 0; i <
NumParts; ++i) {
2130 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2131 {SrcRegs[NumParts - 1 - i]});
2135 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2138 MI.eraseFromParent();
2141 case TargetOpcode::G_PTR_ADD:
2142 case TargetOpcode::G_PTRMASK: {
2150 case TargetOpcode::G_FPTOUI:
2151 case TargetOpcode::G_FPTOSI:
2152 case TargetOpcode::G_FPTOUI_SAT:
2153 case TargetOpcode::G_FPTOSI_SAT:
2155 case TargetOpcode::G_FPEXT:
2162 case TargetOpcode::G_FLDEXP:
2163 case TargetOpcode::G_STRICT_FLDEXP:
2165 case TargetOpcode::G_VSCALE: {
2167 LLT Ty = MRI.getType(Dst);
2171 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2172 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2173 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2176 MI.eraseFromParent();
2183 LLT Ty = MRI.getType(Val);
2184 if (Ty.isScalar() && !Ty.isFloat())
2191 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2193 if (Ty.isPointer()) {
2194 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2196 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2202 if (Ty.isPointerVector())
2203 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2204 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2208 unsigned OpIdx,
unsigned ExtOpcode) {
2210 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2211 MO.
setReg(ExtB.getReg(0));
2217 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2219 MO.
setReg(ExtB.getReg(0));
2225 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2226 MO.
setReg(ExtB.getReg(0));
2230 unsigned OpIdx,
unsigned TruncOpcode) {
2232 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2234 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2241 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2243 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2248 unsigned OpIdx,
unsigned ExtOpcode) {
2250 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2252 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2261 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2263 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2269 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2279 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2286LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2291 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2292 if (DstTy.isVector())
2295 LLT SrcTy =
MRI.getType(Src1Reg);
2296 const int DstSize = DstTy.getSizeInBits();
2297 const int SrcSize = SrcTy.getSizeInBits();
2299 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2301 unsigned NumOps =
MI.getNumOperands();
2302 unsigned NumSrc =
MI.getNumOperands() - 1;
2303 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2305 if (WideSize >= DstSize) {
2309 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2310 const unsigned Offset = (
I - 1) * PartSize;
2318 MRI.createGenericVirtualRegister(WideTy);
2323 ResultReg = NextResult;
2326 if (WideSize > DstSize)
2328 else if (DstTy.isPointer())
2330 else if (DstTy != WideTy)
2333 MI.eraseFromParent();
2358 const int GCD = std::gcd(SrcSize, WideSize);
2368 if (GCD == SrcSize) {
2371 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2372 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2378 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2380 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2384 const int PartsPerGCD = WideSize / GCD;
2388 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2390 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2397 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2399 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2400 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2403 MI.eraseFromParent();
2408LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2413 int NumDst =
MI.getNumOperands() - 1;
2414 Register SrcReg =
MI.getOperand(NumDst).getReg();
2415 LLT SrcTy = MRI.getType(SrcReg);
2419 Register Dst0Reg =
MI.getOperand(0).getReg();
2420 LLT DstTy = MRI.getType(Dst0Reg);
2429 dbgs() <<
"Not casting non-integral address space integer\n");
2434 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2442 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2451 SrcTy = MRI.getType(SrcReg);
2455 for (
int I = 1;
I != NumDst; ++
I) {
2456 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2457 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2461 MI.eraseFromParent();
2472 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2476 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2479 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2497 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2502 if (PartsPerRemerge == 1) {
2505 for (
int I = 0;
I != NumUnmerge; ++
I) {
2506 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2508 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2509 int Idx =
I * PartsPerUnmerge + J;
2511 MIB.addDef(
MI.getOperand(Idx).getReg());
2514 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2518 MIB.addUse(Unmerge.getReg(
I));
2521 SmallVector<Register, 16> Parts;
2522 for (
int J = 0; J != NumUnmerge; ++J)
2523 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2526 for (
int I = 0;
I != NumDst; ++
I) {
2527 for (
int J = 0; J < PartsPerRemerge; ++J) {
2528 const int Idx =
I * PartsPerRemerge + J;
2532 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2533 RemergeParts.
clear();
2537 MI.eraseFromParent();
2542LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2544 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2545 unsigned Offset =
MI.getOperand(2).getImm();
2548 if (SrcTy.
isVector() || DstTy.isVector())
2560 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2564 if (DstTy.isPointer())
2571 MI.eraseFromParent();
2576 LLT ShiftTy = SrcTy;
2585 MI.eraseFromParent();
2616LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2618 if (TypeIdx != 0 || WideTy.
isVector())
2628LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2632 std::optional<Register> CarryIn;
2633 switch (
MI.getOpcode()) {
2636 case TargetOpcode::G_SADDO:
2637 Opcode = TargetOpcode::G_ADD;
2638 ExtOpcode = TargetOpcode::G_SEXT;
2640 case TargetOpcode::G_SSUBO:
2641 Opcode = TargetOpcode::G_SUB;
2642 ExtOpcode = TargetOpcode::G_SEXT;
2644 case TargetOpcode::G_UADDO:
2645 Opcode = TargetOpcode::G_ADD;
2646 ExtOpcode = TargetOpcode::G_ZEXT;
2648 case TargetOpcode::G_USUBO:
2649 Opcode = TargetOpcode::G_SUB;
2650 ExtOpcode = TargetOpcode::G_ZEXT;
2652 case TargetOpcode::G_SADDE:
2653 Opcode = TargetOpcode::G_UADDE;
2654 ExtOpcode = TargetOpcode::G_SEXT;
2655 CarryIn =
MI.getOperand(4).getReg();
2657 case TargetOpcode::G_SSUBE:
2658 Opcode = TargetOpcode::G_USUBE;
2659 ExtOpcode = TargetOpcode::G_SEXT;
2660 CarryIn =
MI.getOperand(4).getReg();
2662 case TargetOpcode::G_UADDE:
2663 Opcode = TargetOpcode::G_UADDE;
2664 ExtOpcode = TargetOpcode::G_ZEXT;
2665 CarryIn =
MI.getOperand(4).getReg();
2667 case TargetOpcode::G_USUBE:
2668 Opcode = TargetOpcode::G_USUBE;
2669 ExtOpcode = TargetOpcode::G_ZEXT;
2670 CarryIn =
MI.getOperand(4).getReg();
2686 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2687 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2691 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2693 .buildInstr(Opcode, {WideTy, CarryOutTy},
2694 {LHSExt, RHSExt, *CarryIn})
2697 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2699 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2700 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2701 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2706 MI.eraseFromParent();
2711LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2713 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2714 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2715 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2716 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2717 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2730 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2737 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2741 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2742 {ShiftL, ShiftR},
MI.getFlags());
2747 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2750 MI.eraseFromParent();
2755LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2764 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2766 LLT SrcTy = MRI.getType(
LHS);
2767 LLT OverflowTy = MRI.getType(OriginalOverflow);
2774 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2775 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2776 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2783 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2785 MachineInstrBuilder Mulo;
2786 if (WideMulCanOverflow)
2787 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2788 {LeftOperand, RightOperand});
2790 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2795 MachineInstrBuilder ExtResult;
2802 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2806 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2809 if (WideMulCanOverflow) {
2817 MI.eraseFromParent();
2823 unsigned Opcode =
MI.getOpcode();
2827 case TargetOpcode::G_ATOMICRMW_XCHG:
2828 case TargetOpcode::G_ATOMICRMW_ADD:
2829 case TargetOpcode::G_ATOMICRMW_SUB:
2830 case TargetOpcode::G_ATOMICRMW_AND:
2831 case TargetOpcode::G_ATOMICRMW_OR:
2832 case TargetOpcode::G_ATOMICRMW_XOR:
2833 case TargetOpcode::G_ATOMICRMW_MIN:
2834 case TargetOpcode::G_ATOMICRMW_MAX:
2835 case TargetOpcode::G_ATOMICRMW_UMIN:
2836 case TargetOpcode::G_ATOMICRMW_UMAX:
2837 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2843 case TargetOpcode::G_ATOMIC_CMPXCHG:
2844 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2851 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2861 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2866 case TargetOpcode::G_EXTRACT:
2867 return widenScalarExtract(
MI, TypeIdx, WideTy);
2868 case TargetOpcode::G_INSERT:
2869 return widenScalarInsert(
MI, TypeIdx, WideTy);
2870 case TargetOpcode::G_MERGE_VALUES:
2871 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2872 case TargetOpcode::G_UNMERGE_VALUES:
2873 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2874 case TargetOpcode::G_SADDO:
2875 case TargetOpcode::G_SSUBO:
2876 case TargetOpcode::G_UADDO:
2877 case TargetOpcode::G_USUBO:
2878 case TargetOpcode::G_SADDE:
2879 case TargetOpcode::G_SSUBE:
2880 case TargetOpcode::G_UADDE:
2881 case TargetOpcode::G_USUBE:
2882 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2883 case TargetOpcode::G_UMULO:
2884 case TargetOpcode::G_SMULO:
2885 return widenScalarMulo(
MI, TypeIdx, WideTy);
2886 case TargetOpcode::G_SADDSAT:
2887 case TargetOpcode::G_SSUBSAT:
2888 case TargetOpcode::G_SSHLSAT:
2889 case TargetOpcode::G_UADDSAT:
2890 case TargetOpcode::G_USUBSAT:
2891 case TargetOpcode::G_USHLSAT:
2892 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2893 case TargetOpcode::G_CTTZ:
2894 case TargetOpcode::G_CTTZ_ZERO_POISON:
2895 case TargetOpcode::G_CTLZ:
2896 case TargetOpcode::G_CTLZ_ZERO_POISON:
2897 case TargetOpcode::G_CTLS:
2898 case TargetOpcode::G_CTPOP: {
2911 case TargetOpcode::G_CTTZ:
2912 case TargetOpcode::G_CTTZ_ZERO_POISON:
2913 case TargetOpcode::G_CTLZ_ZERO_POISON:
2914 ExtOpc = TargetOpcode::G_ANYEXT;
2916 case TargetOpcode::G_CTLS:
2917 ExtOpc = TargetOpcode::G_SEXT;
2920 ExtOpc = TargetOpcode::G_ZEXT;
2923 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2924 LLT CurTy = MRI.getType(SrcReg);
2925 unsigned NewOpc = Opcode;
2926 if (NewOpc == TargetOpcode::G_CTTZ) {
2933 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2935 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2941 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2951 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2953 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2958 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2959 Opcode == TargetOpcode::G_CTLZ
2964 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2965 MI.eraseFromParent();
2968 case TargetOpcode::G_BSWAP: {
2972 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2973 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2974 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2977 MI.getOperand(0).setReg(DstExt);
2981 LLT Ty = MRI.getType(DstReg);
2983 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2984 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2990 case TargetOpcode::G_BITREVERSE: {
2994 LLT Ty = MRI.getType(DstReg);
2997 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2999 MI.getOperand(0).setReg(DstExt);
3002 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
3003 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
3008 case TargetOpcode::G_FREEZE:
3009 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
3016 case TargetOpcode::G_ABS:
3023 case TargetOpcode::G_ADD:
3024 case TargetOpcode::G_AND:
3025 case TargetOpcode::G_MUL:
3026 case TargetOpcode::G_OR:
3027 case TargetOpcode::G_XOR:
3028 case TargetOpcode::G_SUB:
3029 case TargetOpcode::G_SHUFFLE_VECTOR:
3045 case TargetOpcode::G_SBFX:
3046 case TargetOpcode::G_UBFX:
3060 case TargetOpcode::G_SHL:
3080 case TargetOpcode::G_ROTR:
3081 case TargetOpcode::G_ROTL:
3090 case TargetOpcode::G_SDIV:
3091 case TargetOpcode::G_SREM:
3092 case TargetOpcode::G_SMIN:
3093 case TargetOpcode::G_SMAX:
3094 case TargetOpcode::G_ABDS:
3102 case TargetOpcode::G_SDIVREM:
3112 case TargetOpcode::G_ASHR:
3113 case TargetOpcode::G_LSHR:
3117 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3118 : TargetOpcode::G_ZEXT;
3131 case TargetOpcode::G_UDIV:
3132 case TargetOpcode::G_UREM:
3133 case TargetOpcode::G_ABDU:
3140 case TargetOpcode::G_UDIVREM:
3149 case TargetOpcode::G_UMIN:
3150 case TargetOpcode::G_UMAX: {
3151 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3153 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3157 ? TargetOpcode::G_SEXT
3158 : TargetOpcode::G_ZEXT;
3168 case TargetOpcode::G_SELECT:
3178 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3185 case TargetOpcode::G_FPEXT:
3193 case TargetOpcode::G_FPTOSI:
3194 case TargetOpcode::G_FPTOUI:
3195 case TargetOpcode::G_INTRINSIC_LRINT:
3196 case TargetOpcode::G_INTRINSIC_LLRINT:
3197 case TargetOpcode::G_IS_FPCLASS:
3207 case TargetOpcode::G_SITOFP:
3217 case TargetOpcode::G_UITOFP:
3227 case TargetOpcode::G_FPTOSI_SAT:
3228 case TargetOpcode::G_FPTOUI_SAT:
3233 LLT Ty = MRI.getType(OldDst);
3234 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3236 MI.getOperand(0).setReg(ExtReg);
3237 uint64_t ShortBits = Ty.getScalarSizeInBits();
3240 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3251 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3252 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3260 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3268 case TargetOpcode::G_LOAD:
3269 case TargetOpcode::G_SEXTLOAD:
3270 case TargetOpcode::G_ZEXTLOAD:
3271 case TargetOpcode::G_FPEXTLOAD:
3277 case TargetOpcode::G_STORE: {
3281 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3282 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3283 if (!Ty.isScalar()) {
3291 MI.setMemRefs(MF, {NewMMO});
3298 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3299 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3305 case TargetOpcode::G_FPTRUNCSTORE:
3312 case TargetOpcode::G_CONSTANT: {
3315 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3316 MRI.getType(
MI.getOperand(0).getReg()));
3317 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3318 ExtOpc == TargetOpcode::G_ANYEXT) &&
3321 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3325 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3331 case TargetOpcode::G_FCONSTANT: {
3337 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3339 MI.eraseFromParent();
3342 case TargetOpcode::G_IMPLICIT_DEF: {
3348 case TargetOpcode::G_BRCOND:
3354 case TargetOpcode::G_FCMP:
3365 case TargetOpcode::G_ICMP:
3370 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3374 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3375 unsigned ExtOpcode =
3379 ? TargetOpcode::G_SEXT
3380 : TargetOpcode::G_ZEXT;
3387 case TargetOpcode::G_PTR_ADD:
3388 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3394 case TargetOpcode::G_PHI: {
3395 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3398 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3401 OpMBB,
MI.getOperand(
I).getReg(), MRI));
3411 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3414 LLT VecTy = MRI.getType(VecReg);
3418 TargetOpcode::G_ANYEXT);
3432 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3448 LLT VecTy = MRI.getType(VecReg);
3467 case TargetOpcode::G_FADD:
3468 case TargetOpcode::G_FMUL:
3469 case TargetOpcode::G_FSUB:
3470 case TargetOpcode::G_FMA:
3471 case TargetOpcode::G_FMAD:
3472 case TargetOpcode::G_FNEG:
3473 case TargetOpcode::G_FABS:
3474 case TargetOpcode::G_FCANONICALIZE:
3475 case TargetOpcode::G_FMINNUM:
3476 case TargetOpcode::G_FMAXNUM:
3477 case TargetOpcode::G_FMINNUM_IEEE:
3478 case TargetOpcode::G_FMAXNUM_IEEE:
3479 case TargetOpcode::G_FMINIMUM:
3480 case TargetOpcode::G_FMAXIMUM:
3481 case TargetOpcode::G_FMINIMUMNUM:
3482 case TargetOpcode::G_FMAXIMUMNUM:
3483 case TargetOpcode::G_FDIV:
3484 case TargetOpcode::G_FREM:
3485 case TargetOpcode::G_FCEIL:
3486 case TargetOpcode::G_FFLOOR:
3487 case TargetOpcode::G_FCOS:
3488 case TargetOpcode::G_FSIN:
3489 case TargetOpcode::G_FTAN:
3490 case TargetOpcode::G_FACOS:
3491 case TargetOpcode::G_FASIN:
3492 case TargetOpcode::G_FATAN:
3493 case TargetOpcode::G_FATAN2:
3494 case TargetOpcode::G_FCOSH:
3495 case TargetOpcode::G_FSINH:
3496 case TargetOpcode::G_FTANH:
3497 case TargetOpcode::G_FLOG10:
3498 case TargetOpcode::G_FLOG:
3499 case TargetOpcode::G_FLOG2:
3500 case TargetOpcode::G_FRINT:
3501 case TargetOpcode::G_FNEARBYINT:
3502 case TargetOpcode::G_FSQRT:
3503 case TargetOpcode::G_FEXP:
3504 case TargetOpcode::G_FEXP2:
3505 case TargetOpcode::G_FEXP10:
3506 case TargetOpcode::G_FPOW:
3507 case TargetOpcode::G_INTRINSIC_TRUNC:
3508 case TargetOpcode::G_INTRINSIC_ROUND:
3509 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3513 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3519 case TargetOpcode::G_FMODF: {
3529 case TargetOpcode::G_FPOWI:
3530 case TargetOpcode::G_FLDEXP:
3531 case TargetOpcode::G_STRICT_FLDEXP: {
3533 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3554 case TargetOpcode::G_FFREXP: {
3567 case TargetOpcode::G_LROUND:
3568 case TargetOpcode::G_LLROUND:
3579 case TargetOpcode::G_INTTOPTR:
3587 case TargetOpcode::G_PTRTOINT:
3595 case TargetOpcode::G_BUILD_VECTOR: {
3599 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3605 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3613 case TargetOpcode::G_SEXT_INREG:
3622 case TargetOpcode::G_PTRMASK: {
3630 case TargetOpcode::G_VECREDUCE_ADD: {
3639 case TargetOpcode::G_VECREDUCE_FADD:
3640 case TargetOpcode::G_VECREDUCE_FMUL:
3641 case TargetOpcode::G_VECREDUCE_FMIN:
3642 case TargetOpcode::G_VECREDUCE_FMAX:
3643 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3644 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3649 LLT VecTy = MRI.getType(VecReg);
3656 case TargetOpcode::G_VSCALE: {
3663 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3668 case TargetOpcode::G_SPLAT_VECTOR: {
3677 case TargetOpcode::G_INSERT_SUBVECTOR: {
3689 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3690 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3691 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3695 auto SplatZero =
MIRBuilder.buildSplatVector(
3700 MI.eraseFromParent();
3704 case TargetOpcode::G_BITCAST:
3716 if (MRI.getType(Dst) == MRI.getType(Src)) {
3717 Observer.changingAllUsesOfReg(MRI, Dst);
3718 MRI.replaceRegWith(Dst, Src);
3719 Observer.finishedChangingAllUsesOfReg();
3720 MI.eraseFromParent();
3729 auto Unmerge =
B.buildUnmerge(Ty, Src);
3730 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3739 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3741 LLT DstLLT =
MRI.getType(DstReg);
3753 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3762 MI.eraseFromParent();
3770 const ConstantFP *ConstantVal =
MI.getOperand(1).getFPImm();
3773 bool ForCodeSize =
MIRBuilder.getMF().getFunction().hasOptSize();
3774 if (TLI.getFPImmAction(
Imm, MRI.getType(Dst), ForCodeSize) ==
3780 MI.eraseFromParent();
3786 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3787 if (SrcTy.isVector()) {
3791 if (DstTy.isVector()) {
3806 unsigned PieceSize =
3822 MI.eraseFromParent();
3827 LLT::vector(SrcEC * (SrcEltSize / PieceSize), PieceTy);
3829 MIRBuilder.buildBitcast(PiecesVecTy, Src).getReg(0);
3831 MI.eraseFromParent();
3838 LLT DstCastTy = DstEltTy;
3839 LLT SrcPartTy = SrcEltTy;
3843 if (NumSrcElt < NumDstElt) {
3854 SrcPartTy = SrcEltTy;
3855 }
else if (NumSrcElt > NumDstElt) {
3867 DstCastTy = DstEltTy;
3872 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3876 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3877 MI.eraseFromParent();
3881 if (DstTy.isVector()) {
3884 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3885 MI.eraseFromParent();
3901 unsigned NewEltSize,
3902 unsigned OldEltSize) {
3903 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3904 LLT IdxTy =
B.getMRI()->getType(Idx);
3907 auto OffsetMask =
B.buildConstant(
3909 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3910 return B.buildShl(IdxTy, OffsetIdx,
3911 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3926 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3930 unsigned OldNumElts = SrcVecTy.getNumElements();
3937 if (NewNumElts > OldNumElts) {
3948 if (NewNumElts % OldNumElts != 0)
3952 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3956 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3959 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3961 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3962 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3963 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3964 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3965 NewOps[
I] = Elt.getReg(0);
3968 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3970 MI.eraseFromParent();
3974 if (NewNumElts < OldNumElts) {
3975 if (NewEltSize % OldEltSize != 0)
3997 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3998 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4001 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4005 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4006 ScaledIdx).getReg(0);
4014 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
4016 MI.eraseFromParent();
4030 LLT TargetTy =
B.getMRI()->getType(TargetReg);
4031 LLT InsertTy =
B.getMRI()->getType(InsertReg);
4032 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
4033 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
4036 auto EltMask =
B.buildConstant(
4040 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
4041 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
4044 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
4048 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
4062 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
4063 MI.getFirst4RegLLTs();
4075 if (NewNumElts < OldNumElts) {
4076 if (NewEltSize % OldEltSize != 0)
4085 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4086 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4089 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4093 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4094 ScaledIdx).getReg(0);
4104 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4105 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4109 MI.eraseFromParent();
4139 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4143 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4144 return UnableToLegalize;
4149 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4151 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4160 MI.eraseFromParent();
4178 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4179 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4189 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4190 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4192 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4193 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4195 MI.eraseFromParent();
4221 uint64_t Idx = ES->getIndexImm();
4225 LLT DstTy = MRI.getType(Dst);
4226 LLT SrcTy = MRI.getType(Src);
4232 if (DstTy == CastTy)
4240 if (CastEltSize < DstEltSize)
4243 auto AdjustAmt = CastEltSize / DstEltSize;
4244 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4245 SrcTyMinElts % AdjustAmt != 0)
4250 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4251 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4254 ES->eraseFromParent();
4285 uint64_t Idx = ES->getIndexImm();
4289 LLT DstTy = MRI.getType(Dst);
4290 LLT BigVecTy = MRI.getType(BigVec);
4293 if (DstTy == CastTy)
4308 if (CastEltSize < DstEltSize)
4311 auto AdjustAmt = CastEltSize / DstEltSize;
4312 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4313 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4319 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4322 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4325 ES->eraseFromParent();
4333 LLT DstTy = MRI.getType(DstReg);
4343 if (MemSizeInBits != MemStoreSizeInBits) {
4360 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4364 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4365 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4367 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4370 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4372 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4375 if (DstTy != LoadTy)
4383 if (
MIRBuilder.getDataLayout().isBigEndian())
4401 uint64_t LargeSplitSize, SmallSplitSize;
4406 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4413 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4416 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4427 if (Alignment.value() * 8 > MemSizeInBits &&
4432 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4449 LLT PtrTy = MRI.getType(PtrReg);
4455 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4458 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4459 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4460 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4462 SmallPtr, *SmallMMO);
4464 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4465 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4467 if (AnyExtTy == DstTy)
4468 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4470 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4472 if (IntDstTy == DstTy) {
4479 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4485 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4502 LLT SrcTy = MRI.getType(SrcReg);
4510 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4516 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4518 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4522 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4526 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4541 uint64_t LargeSplitSize, SmallSplitSize;
4548 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4551 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4560 if (SrcTy.isPointer()) {
4565 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4568 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4569 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4572 LLT PtrTy = MRI.getType(PtrReg);
4574 LargeSplitSize / 8);
4575 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4581 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4582 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4591 LLT SrcTy = MRI.getType(SrcReg);
4597 assert(SrcTy.isVector() &&
"Expect a vector store type");
4604 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4608 auto Elt =
MIRBuilder.buildExtractVectorElement(
4609 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4610 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4611 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4617 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4618 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4622 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4633 switch (
MI.getOpcode()) {
4634 case TargetOpcode::G_LOAD: {
4652 case TargetOpcode::G_STORE: {
4668 case TargetOpcode::G_SELECT: {
4672 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4674 dbgs() <<
"bitcast action not implemented for vector select\n");
4685 case TargetOpcode::G_AND:
4686 case TargetOpcode::G_OR:
4687 case TargetOpcode::G_XOR: {
4695 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4697 case TargetOpcode::G_INSERT_VECTOR_ELT:
4699 case TargetOpcode::G_CONCAT_VECTORS:
4701 case TargetOpcode::G_SHUFFLE_VECTOR:
4703 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4705 case TargetOpcode::G_INSERT_SUBVECTOR:
4713void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4722 switch(
MI.getOpcode()) {
4725 case TargetOpcode::G_FCONSTANT:
4727 case TargetOpcode::G_BITCAST:
4729 case TargetOpcode::G_SREM:
4730 case TargetOpcode::G_UREM: {
4731 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4733 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4734 {MI.getOperand(1), MI.getOperand(2)});
4736 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4738 MI.eraseFromParent();
4741 case TargetOpcode::G_SADDO:
4742 case TargetOpcode::G_SSUBO:
4744 case TargetOpcode::G_SADDE:
4746 case TargetOpcode::G_SSUBE:
4748 case TargetOpcode::G_UMULH:
4749 case TargetOpcode::G_SMULH:
4751 case TargetOpcode::G_SMULO:
4752 case TargetOpcode::G_UMULO: {
4755 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4756 LLT Ty = MRI.getType(Res);
4758 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4759 ? TargetOpcode::G_SMULH
4760 : TargetOpcode::G_UMULH;
4764 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4765 MI.removeOperand(1);
4768 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4776 if (Opcode == TargetOpcode::G_SMULH) {
4777 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4778 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4785 case TargetOpcode::G_FNEG: {
4786 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4789 Register CastedSubByReg = SubByReg;
4791 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4792 !SubByRegTy.getScalarType().isInteger()) {
4793 auto BitcastDst = SubByRegTy.changeElementType(
4795 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4801 if (ResTy != TyInt) {
4803 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4806 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4808 MI.eraseFromParent();
4811 case TargetOpcode::G_FSUB:
4812 case TargetOpcode::G_STRICT_FSUB: {
4813 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4814 LLT Ty = MRI.getType(Res);
4819 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4820 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4824 MI.eraseFromParent();
4827 case TargetOpcode::G_FMAD:
4829 case TargetOpcode::G_FFLOOR:
4831 case TargetOpcode::G_LROUND:
4832 case TargetOpcode::G_LLROUND: {
4835 LLT SrcTy = MRI.getType(SrcReg);
4836 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4839 MI.eraseFromParent();
4842 case TargetOpcode::G_INTRINSIC_ROUND:
4844 case TargetOpcode::G_FRINT: {
4847 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4850 case TargetOpcode::G_INTRINSIC_LRINT:
4851 case TargetOpcode::G_INTRINSIC_LLRINT: {
4854 LLT SrcTy = MRI.getType(SrcReg);
4856 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4858 MI.eraseFromParent();
4861 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4862 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4863 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4864 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4865 **
MI.memoperands_begin());
4867 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4868 MI.eraseFromParent();
4871 case TargetOpcode::G_LOAD:
4872 case TargetOpcode::G_SEXTLOAD:
4873 case TargetOpcode::G_ZEXTLOAD:
4875 case TargetOpcode::G_STORE:
4877 case TargetOpcode::G_CTLZ_ZERO_POISON:
4878 case TargetOpcode::G_CTTZ_ZERO_POISON:
4879 case TargetOpcode::G_CTLZ:
4880 case TargetOpcode::G_CTTZ:
4881 case TargetOpcode::G_CTPOP:
4882 case TargetOpcode::G_CTLS:
4885 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4887 Register NewRes = MRI.cloneVirtualRegister(Res);
4894 MI.eraseFromParent();
4898 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4899 const LLT CondTy = MRI.getType(CarryOut);
4900 const LLT Ty = MRI.getType(Res);
4902 Register NewRes = MRI.cloneVirtualRegister(Res);
4905 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4911 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4912 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4919 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4924 MI.eraseFromParent();
4928 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4933 MI.eraseFromParent();
4937 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4938 const LLT CondTy = MRI.getType(BorrowOut);
4939 const LLT Ty = MRI.getType(Res);
4942 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4948 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4949 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4956 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4957 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4959 MI.eraseFromParent();
4999 case G_MERGE_VALUES:
5001 case G_UNMERGE_VALUES:
5003 case TargetOpcode::G_SEXT_INREG: {
5004 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
5005 int64_t SizeInBits =
MI.getOperand(2).getImm();
5007 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
5008 LLT DstTy = MRI.getType(DstReg);
5009 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
5012 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
5013 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
5014 MI.eraseFromParent();
5017 case G_EXTRACT_VECTOR_ELT:
5018 case G_INSERT_VECTOR_ELT:
5020 case G_SHUFFLE_VECTOR:
5022 case G_VECTOR_COMPRESS:
5024 case G_DYN_STACKALLOC:
5026 case G_INSERT_SUBVECTOR: {
5027 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
5028 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
5033 Register Subvector =
MI.getOperand(2).getReg();
5034 auto InsertionPointImm =
MI.getOperand(3).getImm();
5037 LLT DstTy = MRI.getType(Subvector);
5041 bool InsertInLowHalf = InsertionPointImm == 0;
5042 auto Extract =
MIRBuilder.buildExtractSubvector(
5044 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
5046 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
5047 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
5049 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
5050 {LowHalf, HighHalf});
5051 MI.eraseFromParent();
5057 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
5058 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
5064 if (i >= InsertionPointImm &&
5066 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
5074 MI.eraseFromParent();
5078 case G_EXTRACT_SUBVECTOR: {
5081 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5083 LLT SrcTy = MRI.getType(SrcReg);
5084 LLT DstTy = MRI.getType(DstReg);
5086 if (SrcTy.isScalable())
5097 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5098 ExtractionPointImm + i)
5102 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5103 MI.eraseFromParent();
5108 case G_STACKRESTORE:
5118 case G_READ_REGISTER:
5119 case G_WRITE_REGISTER:
5126 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5127 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5133 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5138 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5145 case G_TRUNC_SSAT_S:
5146 case G_TRUNC_USAT_U:
5147 case G_TRUNC_SSAT_U:
5153 bool IsSigned =
MI.getOpcode() == G_ABDS;
5154 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5155 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5156 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5179 case G_MEMCPY_INLINE:
5180 case G_MEMSET_INLINE:
5192 case G_ATOMICRMW_SUB: {
5193 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5194 const LLT ValTy = MRI.getType(Val);
5198 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5199 MI.eraseFromParent();
5227 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5231 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5237 Align StackTypeAlign =
5244 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5245 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5250 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5262 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5265 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5276 "Converting bits to bytes lost precision");
5282 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5283 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5285 if (IdxTy != MRI.getType(Index))
5286 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5291 LLT PtrTy = MRI.getType(VecPtr);
5292 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5300 std::initializer_list<unsigned> NonVecOpIndices) {
5301 if (
MI.getNumMemOperands() != 0)
5304 LLT VecTy =
MRI.getType(
MI.getReg(0));
5309 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5318 if (!Ty.isVector()) {
5324 if (Ty.getNumElements() != NumElts)
5339 assert(Ty.isVector() &&
"Expected vector type");
5346 for (
int i = 0; i <
NumParts; ++i) {
5351 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5360 for (
unsigned i = 0; i <
N; ++i) {
5362 Ops.push_back(
Op.getReg());
5363 else if (
Op.isImm())
5364 Ops.push_back(
Op.getImm());
5365 else if (
Op.isPredicate())
5387 std::initializer_list<unsigned> NonVecOpIndices) {
5389 "Non-compatible opcode or not specified non-vector operands");
5390 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5392 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5393 unsigned NumDefs =
MI.getNumDefs();
5401 for (
unsigned i = 0; i < NumDefs; ++i) {
5402 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5410 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5411 ++UseIdx, ++UseNo) {
5414 MI.getOperand(UseIdx));
5423 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5427 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5429 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5430 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5433 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5434 Uses.push_back(InputOpsPieces[InputNo][i]);
5437 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5438 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5443 for (
unsigned i = 0; i < NumDefs; ++i)
5444 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5446 for (
unsigned i = 0; i < NumDefs; ++i)
5447 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5450 MI.eraseFromParent();
5457 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5459 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5460 unsigned NumDefs =
MI.getNumDefs();
5464 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5469 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5470 UseIdx += 2, ++UseNo) {
5479 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5481 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5482 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5484 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5487 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5488 Phi.addUse(InputOpsPieces[j][i]);
5489 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5499 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5501 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5504 MI.eraseFromParent();
5512 const int NumDst =
MI.getNumOperands() - 1;
5513 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5514 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5515 LLT SrcTy = MRI.getType(SrcReg);
5517 if (TypeIdx != 1 || NarrowTy == DstTy)
5524 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5527 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5541 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5542 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5543 const int PartsPerUnmerge = NumDst / NumUnmerge;
5545 for (
int I = 0;
I != NumUnmerge; ++
I) {
5546 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5548 for (
int J = 0; J != PartsPerUnmerge; ++J)
5549 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5550 MIB.addUse(Unmerge.getReg(
I));
5553 MI.eraseFromParent();
5560 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5564 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5566 if (NarrowTy == SrcTy)
5574 assert(SrcTy.isVector() &&
"Expected vector types");
5576 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5590 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5591 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5592 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5598 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5599 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5600 ++i,
Offset += NumNarrowTyElts) {
5603 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5606 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5607 MI.eraseFromParent();
5611 assert(TypeIdx == 0 &&
"Bad type index");
5612 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5628 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5630 for (
unsigned i = 0; i <
NumParts; ++i) {
5632 for (
unsigned j = 0; j < NumElts; ++j)
5633 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5635 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5638 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5639 MI.eraseFromParent();
5647 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5649 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5651 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5653 InsertVal =
MI.getOperand(2).getReg();
5655 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5656 LLT VecTy = MRI.getType(SrcVec);
5662 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5666 MI.eraseFromParent();
5675 SplitPieces[IdxVal] = InsertVal;
5676 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5678 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5682 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5685 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5686 TargetOpcode::G_ANYEXT);
5690 LLT IdxTy = MRI.getType(Idx);
5691 int64_t PartIdx = IdxVal / NewNumElts;
5693 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5696 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5699 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5700 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5701 VecParts[PartIdx] = InsertPart.getReg(0);
5705 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5707 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5711 MI.eraseFromParent();
5731 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5743 LLT ValTy = MRI.getType(ValReg);
5752 int NumLeftover = -1;
5758 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5761 NumLeftover = NarrowLeftoverRegs.
size();
5768 LLT PtrTy = MRI.getType(AddrReg);
5778 auto MMO = LdStMI.
getMMO();
5783 for (
unsigned Idx = 0, E =
NumParts; Idx != E &&
Offset < TotalSize;
5785 unsigned ByteOffset =
Offset / 8;
5788 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5795 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5796 ValRegs.push_back(Dst);
5797 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5799 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5808 unsigned HandledOffset =
5813 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5816 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5817 LeftoverTy, NarrowLeftoverRegs);
5831 switch (
MI.getOpcode()) {
5832 case G_IMPLICIT_DEF:
5848 case G_FCANONICALIZE:
5865 case G_INTRINSIC_LRINT:
5866 case G_INTRINSIC_LLRINT:
5867 case G_INTRINSIC_ROUND:
5868 case G_INTRINSIC_ROUNDEVEN:
5871 case G_INTRINSIC_TRUNC:
5899 case G_FMINNUM_IEEE:
5900 case G_FMAXNUM_IEEE:
5922 case G_CTLZ_ZERO_POISON:
5924 case G_CTTZ_ZERO_POISON:
5941 case G_ADDRSPACE_CAST:
5954 case G_STRICT_FLDEXP:
5956 case G_TRUNC_SSAT_S:
5957 case G_TRUNC_SSAT_U:
5958 case G_TRUNC_USAT_U:
5966 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5971 case G_UNMERGE_VALUES:
5973 case G_BUILD_VECTOR:
5974 assert(TypeIdx == 0 &&
"not a vector type index");
5976 case G_CONCAT_VECTORS:
5980 case G_EXTRACT_SUBVECTOR: {
5982 LLT DstTy = MRI.getType(DstReg);
5984 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5994 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5995 uint64_t RequiredSubvectorIndex =
5999 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
6002 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
6005 MI.eraseFromParent();
6008 case G_EXTRACT_VECTOR_ELT:
6009 case G_INSERT_VECTOR_ELT:
6018 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
6019 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
6021 case G_SHUFFLE_VECTOR:
6027 case G_INTRINSIC_FPTRUNC_ROUND:
6037 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
6038 "Not a bitcast operation");
6043 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
6045 unsigned NewElemCount =
6048 if (NewElemCount == 1) {
6051 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
6058 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
6067 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
6068 MI.eraseFromParent();
6074 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6078 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6079 MI.getFirst3RegLLTs();
6082 if (DstTy != Src1Ty)
6084 if (DstTy != Src2Ty)
6099 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6115 unsigned InputUsed[2] = {-1U, -1U};
6116 unsigned FirstMaskIdx =
High * NewElts;
6117 bool UseBuildVector =
false;
6118 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6120 int Idx = Mask[FirstMaskIdx + MaskOffset];
6125 if (
Input >= std::size(Inputs)) {
6132 Idx -=
Input * NewElts;
6136 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6137 if (InputUsed[OpNo] ==
Input) {
6140 }
else if (InputUsed[OpNo] == -1U) {
6142 InputUsed[OpNo] =
Input;
6147 if (OpNo >= std::size(InputUsed)) {
6150 UseBuildVector =
true;
6155 Ops.push_back(Idx + OpNo * NewElts);
6158 if (UseBuildVector) {
6163 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6165 int Idx = Mask[FirstMaskIdx + MaskOffset];
6170 if (
Input >= std::size(Inputs)) {
6177 Idx -=
Input * NewElts;
6181 .buildExtractVectorElement(
6182 EltTy, Inputs[
Input],
6188 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6189 }
else if (InputUsed[0] == -1U) {
6191 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6192 }
else if (NewElts == 1) {
6193 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6195 Register Op0 = Inputs[InputUsed[0]];
6199 : Inputs[InputUsed[1]];
6201 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6208 MI.eraseFromParent();
6221 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6227 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6232 : SrcTy.getNumElements();
6236 if (DstTy != NarrowTy)
6243 while (NumPartsLeft > 1) {
6244 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6247 .buildInstr(ScalarOpc, {NarrowTy},
6248 {SplitSrcs[Idx], SplitSrcs[Idx + 1]},
6252 SplitSrcs = PartialResults;
6253 PartialResults.
clear();
6254 NumPartsLeft = SplitSrcs.
size();
6258 MI.eraseFromParent();
6263 for (
unsigned Idx = 1; Idx <
NumParts; ++Idx)
6265 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]},
6269 MI.eraseFromParent();
6273 for (
unsigned Part = 0; Part <
NumParts; ++Part) {
6275 .buildInstr(RdxMI.getOpcode(), {DstTy},
6285 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6288 Register Acc = PartialReductions[0];
6289 for (
unsigned Part = 1; Part <
NumParts; ++Part) {
6291 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, {Acc, PartialReductions[Part]},
6295 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]},
6300 MI.eraseFromParent();
6306 unsigned int TypeIdx,
6308 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6309 MI.getFirst3RegLLTs();
6310 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6314 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6315 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6316 "Unexpected vecreduce opcode");
6317 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6318 ? TargetOpcode::G_FADD
6319 : TargetOpcode::G_FMUL;
6322 unsigned NumParts = SrcTy.getNumElements();
6325 for (
unsigned i = 0; i <
NumParts; i++)
6327 .buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]},
6332 MI.eraseFromParent();
6339 unsigned ScalarOpc) {
6347 while (SplitSrcs.
size() > 1) {
6349 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6359 SplitSrcs = std::move(PartialRdxs);
6363 MI.getOperand(1).setReg(SplitSrcs[0]);
6370 const LLT HalfTy,
const LLT AmtTy) {
6372 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6373 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6377 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6378 MI.eraseFromParent();
6384 unsigned VTBits = 2 * NVTBits;
6387 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6388 if (Amt.
ugt(VTBits)) {
6390 }
else if (Amt.
ugt(NVTBits)) {
6393 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6394 }
else if (Amt == NVTBits) {
6402 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6405 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6406 if (Amt.
ugt(VTBits)) {
6408 }
else if (Amt.
ugt(NVTBits)) {
6410 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6412 }
else if (Amt == NVTBits) {
6416 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6418 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6420 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6426 if (Amt.
ugt(VTBits)) {
6428 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6429 }
else if (Amt.
ugt(NVTBits)) {
6431 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6433 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6434 }
else if (Amt == NVTBits) {
6437 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6439 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6441 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6443 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6450 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6451 MI.eraseFromParent();
6467 LLT DstTy = MRI.getType(DstReg);
6472 LLT ShiftAmtTy = MRI.getType(Amt);
6474 if (DstEltSize % 2 != 0)
6501 const unsigned NewBitSize = DstEltSize / 2;
6513 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6515 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6516 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6519 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6520 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6527 switch (
MI.getOpcode()) {
6528 case TargetOpcode::G_SHL: {
6530 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6532 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6533 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6534 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6537 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6538 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6540 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6542 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6544 ResultRegs[0] =
Lo.getReg(0);
6545 ResultRegs[1] =
Hi.getReg(0);
6548 case TargetOpcode::G_LSHR:
6549 case TargetOpcode::G_ASHR: {
6551 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6553 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6554 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6555 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6559 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6562 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6563 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6565 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6569 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6571 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6573 ResultRegs[0] =
Lo.getReg(0);
6574 ResultRegs[1] =
Hi.getReg(0);
6581 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6582 MI.eraseFromParent();
6591 LLT TargetTy,
LLT ShiftAmtTy) {
6594 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6596 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6597 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6598 const bool NeedsInterWordShift = ShiftBits != 0;
6601 case TargetOpcode::G_SHL: {
6604 if (PartIdx < ShiftWords)
6607 unsigned SrcIdx = PartIdx - ShiftWords;
6608 if (!NeedsInterWordShift)
6609 return SrcParts[SrcIdx];
6614 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6618 return Hi.getReg(0);
6621 case TargetOpcode::G_LSHR: {
6622 unsigned SrcIdx = PartIdx + ShiftWords;
6625 if (!NeedsInterWordShift)
6626 return SrcParts[SrcIdx];
6631 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6635 return Lo.getReg(0);
6638 case TargetOpcode::G_ASHR: {
6640 unsigned SrcIdx = PartIdx + ShiftWords;
6643 if (!NeedsInterWordShift)
6644 return SrcParts[SrcIdx];
6675 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6676 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6681 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6690 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6691 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6693 auto IsZeroBitShift =
6701 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6702 : TargetOpcode::G_SHL;
6705 auto TargetBitsConst =
6707 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6712 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6717 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6719 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6723 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6736 LLT DstTy = MRI.getType(DstReg);
6740 const unsigned NumParts = DstBits / TargetBits;
6742 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6752 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6753 MI.eraseFromParent();
6758 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6759 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6765 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6769 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6772 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6773 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6779 Params, TargetTy, ShiftAmtTy);
6781 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6782 MI.eraseFromParent();
6791 LLT DstTy = MRI.getType(DstReg);
6792 LLT ShiftAmtTy = MRI.getType(AmtReg);
6796 const unsigned NumParts = DstBits / TargetBits;
6798 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6815 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6827 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6828 auto TargetBitsLog2Const =
6829 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6830 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6833 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6835 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6843 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6844 auto TargetBitsMinusOneConst =
6845 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6847 .buildAShr(TargetTy, SrcParts[
NumParts - 1],
6848 TargetBitsMinusOneConst)
6851 FillValue = ZeroReg;
6861 Register InBoundsResult = FillValue;
6872 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy,
K);
6874 WordShift, WordShiftKConst);
6886 switch (
MI.getOpcode()) {
6887 case TargetOpcode::G_SHL:
6888 MainSrcIdx = (int)
I - (
int)
K;
6889 CarrySrcIdx = MainSrcIdx - 1;
6891 case TargetOpcode::G_LSHR:
6892 case TargetOpcode::G_ASHR:
6893 MainSrcIdx = (int)
I + (
int)
K;
6894 CarrySrcIdx = MainSrcIdx + 1;
6902 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)
NumParts) {
6903 Register MainOp = SrcParts[MainSrcIdx];
6907 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)
NumParts)
6908 CarryOp = SrcParts[CarrySrcIdx];
6909 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6911 CarryOp = FillValue;
6917 ResultForK = FillValue;
6923 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6930 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6934 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6935 MI.eraseFromParent();
6942 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6945 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6948 OpMBB,
MI.getOperand(
I).getReg(), MRI));
6961 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6966 "getNeutralElementForVecReduce called with invalid opcode!");
6967 case TargetOpcode::G_VECREDUCE_ADD:
6968 case TargetOpcode::G_VECREDUCE_OR:
6969 case TargetOpcode::G_VECREDUCE_XOR:
6970 case TargetOpcode::G_VECREDUCE_UMAX:
6972 case TargetOpcode::G_VECREDUCE_MUL:
6974 case TargetOpcode::G_VECREDUCE_AND:
6975 case TargetOpcode::G_VECREDUCE_UMIN:
6978 case TargetOpcode::G_VECREDUCE_SMAX:
6981 case TargetOpcode::G_VECREDUCE_SMIN:
6984 case TargetOpcode::G_VECREDUCE_FADD:
6986 case TargetOpcode::G_VECREDUCE_FMUL:
6988 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6989 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6990 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6991 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6999 unsigned Opc =
MI.getOpcode();
7001 case TargetOpcode::G_IMPLICIT_DEF:
7002 case TargetOpcode::G_LOAD: {
7010 case TargetOpcode::G_STORE:
7017 case TargetOpcode::G_AND:
7018 case TargetOpcode::G_OR:
7019 case TargetOpcode::G_XOR:
7020 case TargetOpcode::G_ADD:
7021 case TargetOpcode::G_SUB:
7022 case TargetOpcode::G_MUL:
7023 case TargetOpcode::G_FADD:
7024 case TargetOpcode::G_FSUB:
7025 case TargetOpcode::G_FMUL:
7026 case TargetOpcode::G_FDIV:
7027 case TargetOpcode::G_FCOPYSIGN:
7028 case TargetOpcode::G_UADDSAT:
7029 case TargetOpcode::G_USUBSAT:
7030 case TargetOpcode::G_SADDSAT:
7031 case TargetOpcode::G_SSUBSAT:
7032 case TargetOpcode::G_SMIN:
7033 case TargetOpcode::G_SMAX:
7034 case TargetOpcode::G_UMIN:
7035 case TargetOpcode::G_UMAX:
7036 case TargetOpcode::G_FMINNUM:
7037 case TargetOpcode::G_FMAXNUM:
7038 case TargetOpcode::G_FMINNUM_IEEE:
7039 case TargetOpcode::G_FMAXNUM_IEEE:
7040 case TargetOpcode::G_FMINIMUM:
7041 case TargetOpcode::G_FMAXIMUM:
7042 case TargetOpcode::G_FMINIMUMNUM:
7043 case TargetOpcode::G_FMAXIMUMNUM:
7044 case TargetOpcode::G_STRICT_FADD:
7045 case TargetOpcode::G_STRICT_FSUB:
7046 case TargetOpcode::G_STRICT_FMUL: {
7054 case TargetOpcode::G_SHL:
7055 case TargetOpcode::G_ASHR:
7056 case TargetOpcode::G_LSHR: {
7062 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
7068 case TargetOpcode::G_FMA:
7069 case TargetOpcode::G_STRICT_FMA:
7070 case TargetOpcode::G_FSHR:
7071 case TargetOpcode::G_FSHL: {
7080 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
7081 case TargetOpcode::G_EXTRACT:
7088 case TargetOpcode::G_INSERT:
7089 case TargetOpcode::G_INSERT_VECTOR_ELT:
7090 case TargetOpcode::G_FREEZE:
7091 case TargetOpcode::G_FNEG:
7092 case TargetOpcode::G_FABS:
7093 case TargetOpcode::G_FSQRT:
7094 case TargetOpcode::G_FCEIL:
7095 case TargetOpcode::G_FFLOOR:
7096 case TargetOpcode::G_FNEARBYINT:
7097 case TargetOpcode::G_FRINT:
7098 case TargetOpcode::G_INTRINSIC_ROUND:
7099 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7100 case TargetOpcode::G_INTRINSIC_TRUNC:
7101 case TargetOpcode::G_BITREVERSE:
7102 case TargetOpcode::G_BSWAP:
7103 case TargetOpcode::G_FCANONICALIZE:
7104 case TargetOpcode::G_SEXT_INREG:
7105 case TargetOpcode::G_ABS:
7106 case TargetOpcode::G_CTLZ:
7107 case TargetOpcode::G_CTPOP:
7115 case TargetOpcode::G_SELECT: {
7116 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7118 if (!CondTy.isScalar() ||
7124 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7126 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7131 if (CondTy.isVector())
7141 case TargetOpcode::G_UNMERGE_VALUES:
7143 case TargetOpcode::G_PHI:
7145 case TargetOpcode::G_SHUFFLE_VECTOR:
7147 case TargetOpcode::G_BUILD_VECTOR: {
7149 for (
auto Op :
MI.uses()) {
7157 MIRBuilder.buildDeleteTrailingVectorElements(
7158 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7159 MI.eraseFromParent();
7162 case TargetOpcode::G_SEXT:
7163 case TargetOpcode::G_ZEXT:
7164 case TargetOpcode::G_ANYEXT:
7165 case TargetOpcode::G_TRUNC:
7166 case TargetOpcode::G_FPTRUNC:
7167 case TargetOpcode::G_FPEXT:
7168 case TargetOpcode::G_FPTOSI:
7169 case TargetOpcode::G_FPTOUI:
7170 case TargetOpcode::G_FPTOSI_SAT:
7171 case TargetOpcode::G_FPTOUI_SAT:
7172 case TargetOpcode::G_SITOFP:
7173 case TargetOpcode::G_UITOFP:
7174 case TargetOpcode::G_TRUNC_SSAT_S:
7175 case TargetOpcode::G_TRUNC_SSAT_U:
7176 case TargetOpcode::G_TRUNC_USAT_U: {
7183 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7186 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7194 case TargetOpcode::G_ICMP:
7195 case TargetOpcode::G_FCMP: {
7203 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7208 case TargetOpcode::G_BITCAST: {
7212 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7213 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7229 case TargetOpcode::G_VECREDUCE_FADD:
7230 case TargetOpcode::G_VECREDUCE_FMUL:
7231 case TargetOpcode::G_VECREDUCE_ADD:
7232 case TargetOpcode::G_VECREDUCE_MUL:
7233 case TargetOpcode::G_VECREDUCE_AND:
7234 case TargetOpcode::G_VECREDUCE_OR:
7235 case TargetOpcode::G_VECREDUCE_XOR:
7236 case TargetOpcode::G_VECREDUCE_SMAX:
7237 case TargetOpcode::G_VECREDUCE_SMIN:
7238 case TargetOpcode::G_VECREDUCE_UMAX:
7239 case TargetOpcode::G_VECREDUCE_UMIN: {
7240 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7242 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7243 auto NeutralElement = getNeutralElementForVecReduce(
7249 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7250 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7251 NeutralElement, Idx);
7255 MO.
setReg(NewVec.getReg(0));
7267 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7269 unsigned MaskNumElts = Mask.size();
7270 unsigned SrcNumElts = SrcTy.getNumElements();
7273 if (MaskNumElts == SrcNumElts)
7276 if (MaskNumElts < SrcNumElts) {
7284 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7285 MI.getOperand(1).getReg(),
7286 MI.getOperand(2).getReg(), NewMask);
7287 MI.eraseFromParent();
7292 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7293 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7302 MOps1[0] =
MI.getOperand(1).getReg();
7303 MOps2[0] =
MI.getOperand(2).getReg();
7305 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7306 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7310 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7312 if (Idx >=
static_cast<int>(SrcNumElts))
7313 Idx += PaddedMaskNumElts - SrcNumElts;
7318 if (MaskNumElts != PaddedMaskNumElts) {
7320 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7323 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7325 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7330 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7333 MI.eraseFromParent();
7339 unsigned int TypeIdx,
LLT MoreTy) {
7340 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7342 unsigned NumElts = DstTy.getNumElements();
7345 if (DstTy.isVector() && Src1Ty.isVector() &&
7346 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7354 if (DstTy != Src1Ty || DstTy != Src2Ty)
7362 for (
unsigned I = 0;
I != NumElts; ++
I) {
7364 if (Idx <
static_cast<int>(NumElts))
7367 NewMask[
I] = Idx - NumElts + WidenNumElts;
7371 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7372 MI.getOperand(1).getReg(),
7373 MI.getOperand(2).getReg(), NewMask);
7374 MI.eraseFromParent();
7383 unsigned SrcParts = Src1Regs.
size();
7384 unsigned DstParts = DstRegs.
size();
7386 unsigned DstIdx = 0;
7388 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7389 DstRegs[DstIdx] = FactorSum;
7394 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7396 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7397 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7399 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7405 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7406 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7407 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7408 unsigned i = RevI - 1;
7410 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7420 if (DstIdx != DstParts - 1) {
7421 MachineInstrBuilder Uaddo =
7422 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7423 FactorSum = Uaddo.
getReg(0);
7424 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7425 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7426 MachineInstrBuilder Uaddo =
7427 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7428 FactorSum = Uaddo.
getReg(0);
7429 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7430 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7434 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7435 for (
unsigned i = 2; i < Factors.
size(); ++i)
7436 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7439 CarrySumPrevDstIdx = CarrySum;
7440 DstRegs[DstIdx] = FactorSum;
7452 LLT DstType = MRI.getType(DstReg);
7454 if (DstType.isVector())
7457 unsigned Opcode =
MI.getOpcode();
7458 unsigned OpO, OpE, OpF;
7460 case TargetOpcode::G_SADDO:
7461 case TargetOpcode::G_SADDE:
7462 case TargetOpcode::G_UADDO:
7463 case TargetOpcode::G_UADDE:
7464 case TargetOpcode::G_ADD:
7465 OpO = TargetOpcode::G_UADDO;
7466 OpE = TargetOpcode::G_UADDE;
7467 OpF = TargetOpcode::G_UADDE;
7468 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7469 OpF = TargetOpcode::G_SADDE;
7471 case TargetOpcode::G_SSUBO:
7472 case TargetOpcode::G_SSUBE:
7473 case TargetOpcode::G_USUBO:
7474 case TargetOpcode::G_USUBE:
7475 case TargetOpcode::G_SUB:
7476 OpO = TargetOpcode::G_USUBO;
7477 OpE = TargetOpcode::G_USUBE;
7478 OpF = TargetOpcode::G_USUBE;
7479 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7480 OpF = TargetOpcode::G_SSUBE;
7487 unsigned NumDefs =
MI.getNumExplicitDefs();
7488 Register Src1 =
MI.getOperand(NumDefs).getReg();
7489 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7492 CarryDst =
MI.getOperand(1).getReg();
7493 if (
MI.getNumOperands() == NumDefs + 3)
7494 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7496 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7497 LLT LeftoverTy, DummyTy;
7499 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7504 int NarrowParts = Src1Regs.
size();
7505 Src1Regs.
append(Src1Left);
7506 Src2Regs.
append(Src2Left);
7509 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7511 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7514 if (i == e - 1 && CarryDst)
7515 CarryOut = CarryDst;
7517 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7520 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7521 {Src1Regs[i], Src2Regs[i]});
7522 }
else if (i == e - 1) {
7523 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7524 {Src1Regs[i], Src2Regs[i], CarryIn});
7526 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7527 {Src1Regs[i], Src2Regs[i], CarryIn});
7533 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7534 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7535 ArrayRef(DstRegs).drop_front(NarrowParts));
7537 MI.eraseFromParent();
7543 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7545 LLT Ty = MRI.getType(DstReg);
7549 unsigned Size = Ty.getSizeInBits();
7551 if (
Size % NarrowSize != 0)
7555 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH ||
7556 MI.getOpcode() == TargetOpcode::G_SMULH;
7557 unsigned DstTmpParts =
NumParts * (IsMulHigh ? 2 : 1);
7563 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7568 if (
MI.getOpcode() == TargetOpcode::G_SMULH) {
7569 Register UnsignedHigh = MRI.createGenericVirtualRegister(Ty);
7570 MIRBuilder.buildMergeLikeInstr(UnsignedHigh, DstRegs);
7573 auto ShiftAmt =
MIRBuilder.buildConstant(NarrowTy, NarrowSize - 1);
7576 MIRBuilder.buildAShr(NarrowTy, Src1Parts.back(), ShiftAmt.getReg(0));
7578 MIRBuilder.buildAShr(NarrowTy, Src2Parts.back(), ShiftAmt.getReg(0));
7584 auto SignA =
MIRBuilder.buildMergeLikeInstr(Ty, SignAParts);
7585 auto SignB =
MIRBuilder.buildMergeLikeInstr(Ty, SignBParts);
7589 auto Ca =
MIRBuilder.buildAnd(Ty, SignA, Src2);
7590 auto Cb =
MIRBuilder.buildAnd(Ty, SignB, Src1);
7593 auto Tmp =
MIRBuilder.buildSub(Ty, UnsignedHigh, Ca);
7596 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7599 MI.eraseFromParent();
7609 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7612 LLT SrcTy = MRI.getType(Src);
7624 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7637 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7640 if (SizeOp1 % NarrowSize != 0)
7642 int NumParts = SizeOp1 / NarrowSize;
7649 uint64_t OpStart =
MI.getOperand(2).getImm();
7650 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7651 for (
int i = 0; i <
NumParts; ++i) {
7652 unsigned SrcStart = i * NarrowSize;
7654 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7657 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7665 int64_t ExtractOffset;
7667 if (OpStart < SrcStart) {
7669 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7671 ExtractOffset = OpStart - SrcStart;
7672 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7676 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7678 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7679 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7686 if (MRI.getType(DstReg).isVector())
7687 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7688 else if (DstRegs.
size() > 1)
7689 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7692 MI.eraseFromParent();
7704 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7706 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7709 SrcRegs.
append(LeftoverRegs);
7713 uint64_t OpStart =
MI.getOperand(3).getImm();
7714 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7715 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7716 unsigned DstStart =
I * NarrowSize;
7718 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7726 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7728 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7732 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7740 int64_t ExtractOffset, InsertOffset;
7742 if (OpStart < DstStart) {
7744 ExtractOffset = DstStart - OpStart;
7745 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7747 InsertOffset = OpStart - DstStart;
7749 SegSize = std::min(NarrowSize - InsertOffset, OpSize);
7753 if (ExtractOffset != 0 || SegSize != OpSize) {
7755 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7756 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7759 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7760 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7764 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7768 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7771 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7773 MI.eraseFromParent();
7781 LLT DstTy = MRI.getType(DstReg);
7783 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7789 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7790 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7794 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7795 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7798 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7799 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7800 {Src0Regs[I], Src1Regs[I]});
7804 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7807 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7808 DstLeftoverRegs.
push_back(Inst.getReg(0));
7811 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7812 LeftoverTy, DstLeftoverRegs);
7814 MI.eraseFromParent();
7824 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7826 LLT DstTy = MRI.getType(DstReg);
7831 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7832 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7833 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7835 MI.eraseFromParent();
7845 Register CondReg =
MI.getOperand(1).getReg();
7846 LLT CondTy = MRI.getType(CondReg);
7847 if (CondTy.isVector())
7851 LLT DstTy = MRI.getType(DstReg);
7857 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7858 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7862 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7863 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7866 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7868 CondReg, Src1Regs[
I], Src2Regs[
I]);
7872 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7874 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7878 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7879 LeftoverTy, DstLeftoverRegs);
7881 MI.eraseFromParent();
7891 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7894 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7895 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7898 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7900 auto C_0 =
B.buildConstant(NarrowTy, 0);
7902 UnmergeSrc.getReg(1), C_0);
7903 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7904 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7905 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7906 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7907 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7908 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7910 MI.eraseFromParent();
7923 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7926 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7927 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7930 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7932 auto C_0 =
B.buildConstant(NarrowTy, 0);
7934 UnmergeSrc.getReg(0), C_0);
7935 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7936 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7937 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7938 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7939 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7940 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7942 MI.eraseFromParent();
7955 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7958 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7963 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7967 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7968 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7976 auto LoInv =
B.buildXor(DstTy,
Lo,
Sign);
7977 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7980 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7981 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7983 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7985 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7987 MI.eraseFromParent();
7997 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8000 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
8001 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
8003 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
8004 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
8005 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
8007 MI.eraseFromParent();
8022 LLT ExpTy = MRI.getType(ExpReg);
8027 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
8028 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
8029 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
8030 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
8032 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
8034 MI.getOperand(2).setReg(Trunc.getReg(0));
8041 unsigned Opc =
MI.getOpcode();
8044 auto QAction = LI.getAction(Q).Action;
8050 case TargetOpcode::G_CTLZ_ZERO_POISON: {
8053 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
8057 case TargetOpcode::G_CTLZ: {
8058 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8059 unsigned Len = SrcTy.getScalarSizeInBits();
8061 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
8063 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
8064 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
8067 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8068 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
8069 MI.eraseFromParent();
8085 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
8086 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
8089 Op = MIBOp.getReg(0);
8094 MI.eraseFromParent();
8097 case TargetOpcode::G_CTTZ_ZERO_POISON: {
8100 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
8104 case TargetOpcode::G_CTTZ: {
8105 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8107 unsigned Len = SrcTy.getScalarSizeInBits();
8108 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
8111 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
8115 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
8116 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
8117 MI.eraseFromParent();
8124 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8125 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8127 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8128 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8129 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8130 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8133 MI.eraseFromParent();
8137 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8138 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8142 case TargetOpcode::G_CTPOP: {
8144 LLT Ty = MRI.getType(SrcReg);
8145 unsigned Size = Ty.getScalarSizeInBits();
8157 auto C_1 =
B.buildConstant(Ty, 1);
8158 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8160 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8161 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8162 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8166 auto C_2 =
B.buildConstant(Ty, 2);
8167 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8169 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8170 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8171 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8172 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8179 auto C_4 =
B.buildConstant(Ty, 4);
8180 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8181 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8183 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8184 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8186 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8189 if (
Size == 16 && !Ty.isVector()) {
8191 auto C_8 =
B.buildConstant(Ty, 8);
8192 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8193 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8194 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8195 MI.eraseFromParent();
8204 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8206 auto IsMulSupported = [
this](
const LLT Ty) {
8207 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8210 if (IsMulSupported(Ty)) {
8211 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8212 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8214 auto ResTmp = B8Count;
8215 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8216 auto ShiftC =
B.buildConstant(Ty, Shift);
8217 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8218 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8220 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8222 MI.eraseFromParent();
8225 case TargetOpcode::G_CTLS: {
8226 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8230 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8231 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8233 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8239 MI.eraseFromParent();
8269 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8270 LLT Ty = MRI.getType(Dst);
8271 LLT ShTy = MRI.getType(Z);
8278 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8279 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8289 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8302 MI.eraseFromParent();
8308 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8309 LLT Ty = MRI.getType(Dst);
8310 LLT ShTy = MRI.getType(Z);
8313 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8327 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8328 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8329 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8330 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8331 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8337 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8340 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8343 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8345 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8346 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8347 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8350 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8352 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8354 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8357 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8358 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8363 MI.eraseFromParent();
8374 LLT Ty = MRI.getType(Dst);
8375 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8377 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8378 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8381 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8382 return lowerFunnelShiftAsShifts(
MI);
8386 if (Result == UnableToLegalize)
8387 return lowerFunnelShiftAsShifts(
MI);
8392 auto [Dst, Src] =
MI.getFirst2Regs();
8393 LLT DstTy = MRI.getType(Dst);
8394 LLT SrcTy = MRI.getType(Src);
8398 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8406 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8410 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8414 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8419 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8420 {UnmergeSrc.getReg(0)});
8421 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8422 {UnmergeSrc.getReg(1)});
8425 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8427 MI.eraseFromParent();
8444 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8448 LLT DstTy = MRI.getType(DstReg);
8449 LLT SrcTy = MRI.getType(SrcReg);
8457 SrcTy.getElementCount().divideCoefficientBy(2));
8470 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8482 MI.eraseFromParent();
8491 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8493 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8494 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8496 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8497 MI.eraseFromParent();
8502 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8504 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8505 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8510 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8511 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8513 return lowerRotateWithReverseRotate(
MI);
8516 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8517 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8518 bool IsFShLegal =
false;
8519 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8520 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8524 MI.eraseFromParent();
8529 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8532 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8537 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8538 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8539 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8551 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8553 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8560 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8561 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8563 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8565 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8569 MIRBuilder.
buildOr(Dst, ShVal, RevShiftVal, OrFlags);
8570 MI.eraseFromParent();
8578 auto [Dst, Src] =
MI.getFirst2Regs();
8583 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8596 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8598 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8603 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8605 MI.eraseFromParent();
8613 auto [Dst, Src] =
MI.getFirst2Regs();
8617 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8628 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8629 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8631 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8638 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8639 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8640 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8642 MI.eraseFromParent();
8653 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8654 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8660 MI.eraseFromParent();
8665 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8671 MI.eraseFromParent();
8675 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8695 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8705 MI.eraseFromParent();
8709 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8715 if (DstTy.getScalarSizeInBits() == 32) {
8722 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8723 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8725 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8732 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8733 MI.eraseFromParent();
8741 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8745 if (SrcTy !=
S64 && SrcTy !=
S32)
8747 if (DstTy !=
S32 && DstTy !=
S64)
8774 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8776 MI.eraseFromParent();
8781 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8786 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8793 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8795 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8796 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8798 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8799 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8801 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8803 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8804 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8805 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8808 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8809 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8810 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8812 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask,
K);
8815 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8820 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8821 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8827 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8832 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8837 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8838 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8840 MI.eraseFromParent();
8846 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8848 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8849 unsigned SatWidth = DstTy.getScalarSizeInBits();
8853 APInt MinInt, MaxInt;
8876 if (AreExactFloatBounds) {
8878 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8881 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8883 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8892 MI.eraseFromParent();
8897 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8902 MI.eraseFromParent();
8909 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8917 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8927 MI.eraseFromParent();
8933 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8937 MI.eraseFromParent();
8944 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8945 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8946 "Only G_FPEXT and G_FPTRUNC are expected");
8948 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8953 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8955 StoreOpc = TargetOpcode::G_STORE;
8956 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8959 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8960 LoadOpc = TargetOpcode::G_LOAD;
8969 StackTy, StackTyAlign);
8970 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8973 StackTy, StackTyAlign);
8974 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8976 MI.eraseFromParent();
8984 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8985 assert(SrcTy.getScalarType().isBFloat16() &&
8986 "expected a bf16 source for bf16 fpext lowering");
8997 if (DstTy.getScalarType().isFloat32())
9002 MI.eraseFromParent();
9007 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9008 if (SrcTy.getScalarType().isBFloat16() &&
9009 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
9021 auto [Dst, Src] =
MI.getFirst2Regs();
9025 if (MRI.getType(Src).isVector())
9029 unsigned Flags =
MI.getFlags();
9032 MI.eraseFromParent();
9036 const unsigned ExpMask = 0x7ff;
9037 const unsigned ExpBiasf64 = 1023;
9038 const unsigned ExpBiasf16 = 15;
9040 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
9050 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
9057 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
9061 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
9065 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
9067 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200,
Zero);
9069 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
9070 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
9078 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
9090 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9101 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9117 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9127 MI.eraseFromParent();
9134 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9142 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9168 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9170 MI.eraseFromParent();
9179 LLT OperandTy = MRI.getType(
Op);
9189 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9191 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9192 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9193 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9195 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9203 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9206 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9208 AbsWide, AbsNarrowAsWide);
9212 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9213 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9215 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9216 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9222 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9228 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9229 MI.eraseFromParent();
9235 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9236 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9239 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9242 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9249 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9250 LLT Ty = MRI.getType(Dst);
9252 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9253 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9254 MI.eraseFromParent();
9259 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9260 LLT Ty = MRI.getType(Src);
9261 auto Flags =
MI.getFlags();
9269 FracToUse = FracPart.getReg(0);
9271 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9277 FracToUse =
Select.getReg(0);
9280 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9283 MI.eraseFromParent();
9289 case TargetOpcode::G_SMIN:
9291 case TargetOpcode::G_SMAX:
9293 case TargetOpcode::G_UMIN:
9295 case TargetOpcode::G_UMAX:
9303 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9308 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9309 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9311 MI.eraseFromParent();
9320 LLT DstTy = MRI.getType(Dst);
9321 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9332 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9334 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9337 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9338 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9339 if (TLI.preferSelectsOverBooleanArithmetic(
9342 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9343 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One,
Zero);
9345 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9346 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9352 unsigned BoolExtOp =
9354 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9355 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9359 MI.eraseFromParent();
9365 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9366 const int Src0Size = Src0Ty.getScalarSizeInBits();
9367 const int Src1Size = Src1Ty.getScalarSizeInBits();
9377 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9378 Src0Ty.getScalarType().isInteger()))
9379 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9381 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9382 Src1Ty.getScalarType().isInteger()))
9383 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9388 auto NotSignBitMask =
MIRBuilder.buildConstant(
9392 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9394 if (Src0Ty == Src1Ty) {
9395 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9396 }
else if (Src0Size > Src1Size) {
9397 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9398 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9399 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9400 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9402 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9403 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9404 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9405 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9411 unsigned Flags =
MI.getFlags();
9416 if (DstTy == DstIntTy)
9417 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9423 MI.eraseFromParent();
9434 switch (
MI.getOpcode()) {
9435 case TargetOpcode::G_FMINNUM:
9436 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9438 case TargetOpcode::G_FMINIMUMNUM:
9439 NewOp = TargetOpcode::G_FMINNUM;
9441 case TargetOpcode::G_FMAXNUM:
9442 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9444 case TargetOpcode::G_FMAXIMUMNUM:
9445 NewOp = TargetOpcode::G_FMAXNUM;
9451 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9452 LLT Ty = MRI.getType(Dst);
9461 if (!VT->isKnownNeverSNaN(Src0))
9462 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9464 if (!VT->isKnownNeverSNaN(Src1))
9465 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9470 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9471 MI.eraseFromParent();
9477 unsigned Opc =
MI.getOpcode();
9478 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9479 LLT Ty = MRI.getType(Dst);
9482 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9484 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9485 unsigned OpcNonIeee =
9486 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9487 bool MinMaxMustRespectOrderedZero =
false;
9491 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9493 MinMaxMustRespectOrderedZero =
true;
9494 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9499 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9504 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9507 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9511 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9513 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9525 const unsigned Flags =
MI.getFlags();
9531 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9533 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9535 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9537 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9539 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9544 MI.eraseFromParent();
9551 LLT Ty = MRI.getType(DstReg);
9552 unsigned Flags =
MI.getFlags();
9557 MI.eraseFromParent();
9563 auto [DstReg,
X] =
MI.getFirst2Regs();
9564 const unsigned Flags =
MI.getFlags();
9565 const LLT Ty = MRI.getType(DstReg);
9577 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9579 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9584 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9587 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9589 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9591 MI.eraseFromParent();
9596 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9597 unsigned Flags =
MI.getFlags();
9598 LLT Ty = MRI.getType(DstReg);
9605 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9609 SrcReg,
Zero, Flags);
9611 SrcReg, Trunc, Flags);
9615 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9616 MI.eraseFromParent();
9622 const unsigned NumOps =
MI.getNumOperands();
9623 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9624 unsigned PartSize = Src0Ty.getSizeInBits();
9629 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9630 const unsigned Offset = (
I - 1) * PartSize;
9633 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9636 MRI.createGenericVirtualRegister(WideTy);
9639 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9640 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9641 ResultReg = NextResult;
9644 if (DstTy.isPointer()) {
9645 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9646 DstTy.getAddressSpace())) {
9652 }
else if (WideTy != DstTy) {
9656 MI.eraseFromParent();
9662 const unsigned NumDst =
MI.getNumOperands() - 1;
9663 Register SrcReg =
MI.getOperand(NumDst).getReg();
9664 Register Dst0Reg =
MI.getOperand(0).getReg();
9665 LLT DstTy = MRI.getType(Dst0Reg);
9674 LLT IntTy = MRI.getType(SrcReg);
9679 unsigned Offset = DstSize;
9680 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9682 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9686 MI.eraseFromParent();
9705 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9706 InsertVal =
MI.getOperand(2).getReg();
9708 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9710 LLT VecTy = MRI.getType(SrcVec);
9720 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9721 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9723 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9726 MI.eraseFromParent();
9731 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9742 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9749 int64_t
Offset = IdxVal * EltBytes;
9760 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9763 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9765 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9768 MI.eraseFromParent();
9774 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9775 MI.getFirst3RegLLTs();
9785 for (
int Idx : Mask) {
9787 if (!
Undef.isValid())
9793 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9795 int NumElts = Src0Ty.getNumElements();
9796 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9797 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9798 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9800 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9802 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9807 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9808 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9809 MI.eraseFromParent();
9815 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9816 MI.getFirst4RegLLTs();
9818 if (VecTy.isScalableVector())
9834 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9839 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9842 std::optional<APInt> PassthruSplatVal =
9845 if (PassthruSplatVal.has_value()) {
9847 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9848 }
else if (HasPassthru) {
9849 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9850 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9856 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9860 unsigned NumElmts = VecTy.getNumElements();
9861 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9863 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9866 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9869 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9874 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9876 if (HasPassthru &&
I == NumElmts - 1) {
9879 auto AllLanesSelected =
MIRBuilder.buildICmp(
9881 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9882 {OutPos, EndOfVector});
9886 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9888 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9893 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9895 MI.eraseFromParent();
9912 if (Alignment >
Align(1)) {
9913 APInt AlignMask(
IntPtrTy.getSizeInBits(), Alignment.value(),
true);
9924 const auto &MF = *
MI.getMF();
9930 Register AllocSize =
MI.getOperand(1).getReg();
9933 LLT PtrTy = MRI.getType(Dst);
9934 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9941 MI.eraseFromParent();
9947 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9952 MI.eraseFromParent();
9958 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9963 MI.eraseFromParent();
9969 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9970 unsigned Offset =
MI.getOperand(2).getImm();
9973 if (SrcTy.isVector()) {
9974 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9975 unsigned DstSize = DstTy.getSizeInBits();
9977 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9978 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9980 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9984 for (
unsigned Idx =
Offset / SrcEltSize;
9985 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9986 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9988 if (SubVectorElts.
size() == 1)
9989 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9991 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9993 MI.eraseFromParent();
9999 if ((SrcTy.isPointer() &&
10000 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
10001 (DstTy.isPointer() &&
10002 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
10003 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10007 if ((DstTy.isScalar() || DstTy.isPointer()) &&
10008 (SrcTy.isScalar() || SrcTy.isPointer() ||
10009 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
10010 LLT SrcIntTy = SrcTy;
10011 if (!SrcTy.isScalar()) {
10013 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
10017 if (DstTy.isPointer())
10019 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
10025 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
10029 if (DstTy.isPointer())
10030 MIRBuilder.buildIntToPtr(DstReg, ResultReg);
10032 MI.eraseFromParent();
10040 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
10041 uint64_t
Offset =
MI.getOperand(3).getImm();
10043 LLT DstTy = MRI.getType(Src);
10044 LLT InsertTy = MRI.getType(InsertSrc);
10047 bool IsNonIntegralInsert =
10057 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
10058 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10065 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
10067 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
10071 for (; Idx <
Offset / EltSize; ++Idx) {
10072 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10077 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
10078 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
10080 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
10084 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
10086 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
10093 DstElts.
push_back(UnmergeSrc.getReg(Idx));
10096 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
10097 MI.eraseFromParent();
10106 if (IsNonIntegralDst || IsNonIntegralInsert) {
10107 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10111 LLT IntDstTy = DstTy;
10115 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
10120 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
10126 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10132 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10133 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10134 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10137 MI.eraseFromParent();
10143 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10144 MI.getFirst4RegLLTs();
10145 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10148 LLT BoolTy = Dst1Ty;
10150 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10165 auto ResultLowerThanLHS =
10169 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10173 auto LHSLessThanRHS =
10175 auto ResultNegative =
10177 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10181 MI.eraseFromParent();
10187 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10188 const LLT Ty = MRI.getType(Res);
10191 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10192 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10193 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10197 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10198 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10204 MI.eraseFromParent();
10209 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10210 const LLT Ty = MRI.getType(Res);
10213 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10214 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10215 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10219 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10220 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10225 MI.eraseFromParent();
10231 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10232 LLT Ty = MRI.getType(Res);
10236 switch (
MI.getOpcode()) {
10239 case TargetOpcode::G_UADDSAT:
10242 BaseOp = TargetOpcode::G_ADD;
10244 case TargetOpcode::G_SADDSAT:
10247 BaseOp = TargetOpcode::G_ADD;
10249 case TargetOpcode::G_USUBSAT:
10252 BaseOp = TargetOpcode::G_SUB;
10254 case TargetOpcode::G_SSUBSAT:
10257 BaseOp = TargetOpcode::G_SUB;
10272 uint64_t NumBits = Ty.getScalarSizeInBits();
10283 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10291 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10296 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10297 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10300 MI.eraseFromParent();
10306 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10307 LLT Ty = MRI.getType(Res);
10311 unsigned OverflowOp;
10312 switch (
MI.getOpcode()) {
10315 case TargetOpcode::G_UADDSAT:
10318 OverflowOp = TargetOpcode::G_UADDO;
10320 case TargetOpcode::G_SADDSAT:
10323 OverflowOp = TargetOpcode::G_SADDO;
10325 case TargetOpcode::G_USUBSAT:
10328 OverflowOp = TargetOpcode::G_USUBO;
10330 case TargetOpcode::G_SSUBSAT:
10333 OverflowOp = TargetOpcode::G_SSUBO;
10338 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10339 Register Tmp = OverflowRes.getReg(0);
10340 Register Ov = OverflowRes.getReg(1);
10349 uint64_t NumBits = Ty.getScalarSizeInBits();
10350 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10362 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10364 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10366 MI.eraseFromParent();
10372 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10373 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10374 "Expected shlsat opcode!");
10375 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10376 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10377 LLT Ty = MRI.getType(Res);
10381 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10382 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10391 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10396 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10398 MI.eraseFromParent();
10404 unsigned Opc =
MI.getOpcode();
10405 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
10406 unsigned DstSize = DstTy.getScalarSizeInBits();
10407 unsigned SrcSize = SrcTy.getScalarSizeInBits();
10409 if (
Opc == TargetOpcode::G_TRUNC_SSAT_S) {
10412 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10415 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10416 }
else if (
Opc == TargetOpcode::G_TRUNC_USAT_U) {
10419 Src =
MIRBuilder.buildUMin(SrcTy, Src, Max).getReg(0);
10420 }
else if (
Opc == TargetOpcode::G_TRUNC_SSAT_U) {
10423 Src =
MIRBuilder.buildSMin(SrcTy, Src, Max).getReg(0);
10425 Src =
MIRBuilder.buildSMax(SrcTy, Src, Min).getReg(0);
10431 MI.eraseFromParent();
10436 auto [Dst, Src] =
MI.getFirst2Regs();
10437 const LLT Ty = MRI.getType(Src);
10438 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10439 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10442 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10443 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10444 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10445 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10448 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10451 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10452 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10454 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10455 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10456 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10458 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10459 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10460 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10462 Res.getInstr()->getOperand(0).setReg(Dst);
10464 MI.eraseFromParent();
10471 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10474 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10475 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10476 return B.buildOr(Dst,
LHS,
RHS);
10481 auto [Dst, Src] =
MI.getFirst2Regs();
10482 const LLT SrcTy = MRI.getType(Src);
10483 unsigned Size = SrcTy.getScalarSizeInBits();
10484 unsigned VSize = SrcTy.getSizeInBits();
10487 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10488 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10489 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10490 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10495 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10496 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10497 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10501 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10524 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10528 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10531 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10535 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10539 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10544 MI.eraseFromParent();
10552 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10553 int NameOpIdx = IsRead ? 1 : 0;
10554 int ValRegIndex = IsRead ? 0 : 1;
10556 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10557 const LLT Ty = MRI.getType(ValReg);
10559 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10566 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10567 Fn,
MI.getDebugLoc()));
10571 MI.eraseFromParent();
10580 MI.eraseFromParent();
10586 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10587 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10588 Register Result =
MI.getOperand(0).getReg();
10589 LLT OrigTy = MRI.getType(Result);
10593 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10594 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10596 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10598 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10599 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10602 MI.eraseFromParent();
10608 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10613 MI.eraseFromParent();
10618 MI.eraseFromParent();
10625 unsigned BitSize = SrcTy.getScalarSizeInBits();
10629 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10636 APInt ExpMask = Inf;
10638 APInt QNaNBitMask =
10642 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10643 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10644 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10645 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10646 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10648 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10652 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10654 LLT DstTyCopy = DstTy;
10656 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10684 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10687 Mask &= ~PartialCheck;
10696 else if (PartialCheck ==
fcZero)
10708 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10709 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10710 auto SubnormalRes =
10712 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10715 appendToRes(SubnormalRes);
10722 else if (PartialCheck ==
fcInf)
10727 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10734 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10735 if (PartialCheck ==
fcNan) {
10739 }
else if (PartialCheck ==
fcQNan) {
10749 Abs, InfWithQnanBitC);
10750 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10757 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10759 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10760 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10763 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10769 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10771 appendToRes(NormalRes);
10775 MI.eraseFromParent();
10781 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10782 MI.getFirst4RegLLTs();
10791 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10792 Op1Ty = MRI.getType(Op1Reg);
10793 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10794 Op2Ty = MRI.getType(Op2Reg);
10798 if (MaskTy.isScalar()) {
10806 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10809 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10811 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10813 if (DstTy.isVector()) {
10815 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10816 MaskReg = ShufSplat.getReg(0);
10820 }
else if (!DstTy.isVector()) {
10825 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10829 if (!Op1Ty.getScalarType().isAnyScalar() &&
10830 !Op1Ty.getScalarType().isInteger())
10831 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10833 if (!Op2Ty.getScalarType().isAnyScalar() &&
10834 !Op2Ty.getScalarType().isInteger()) {
10836 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10837 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10840 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10841 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10842 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10847 if (DstTy == Op1TyInt)
10850 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10854 MI.eraseFromParent();
10860 unsigned Opcode =
MI.getOpcode();
10863 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10864 : TargetOpcode::G_UDIV,
10865 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10867 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10868 : TargetOpcode::G_UREM,
10869 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10870 MI.eraseFromParent();
10880 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10884 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10887 MI.eraseFromParent();
10897 Register SrcReg =
MI.getOperand(1).getReg();
10898 LLT Ty = MRI.getType(SrcReg);
10902 MI.eraseFromParent();
10908 Register SrcReg =
MI.getOperand(1).getReg();
10909 Register DestReg =
MI.getOperand(0).getReg();
10915 MI.eraseFromParent();
10921 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10922 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10923 "Expected G_ABDS or G_ABDU instruction");
10925 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10926 LLT Ty = MRI.getType(LHS);
10936 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10938 MI.eraseFromParent();
10944 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10945 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10946 "Expected G_ABDS or G_ABDU instruction");
10948 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10949 LLT Ty = MRI.getType(LHS);
10954 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10955 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10956 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10958 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10959 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10961 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10963 MI.eraseFromParent();
10968 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10973 if (!(SrcTy.getScalarType().isAnyScalar() ||
10974 SrcTy.getScalarType().isInteger())) {
10976 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10977 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10980 if (MRI.getType(DstReg) != TyInt) {
10984 .buildAnd(TyInt, CastedSrc,
10987 DstTy.getScalarSizeInBits())))
10999 MI.eraseFromParent();
11005 Register SrcReg =
MI.getOperand(1).getReg();
11006 LLT SrcTy = MRI.getType(SrcReg);
11007 LLT DstTy = MRI.getType(SrcReg);
11010 if (SrcTy.isScalar()) {
11015 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
11026 Register ListPtr =
MI.getOperand(1).getReg();
11027 LLT PtrTy = MRI.getType(ListPtr);
11034 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
11036 const Align A(
MI.getOperand(2).getImm());
11038 if (
A > TLI.getMinStackArgumentAlignment()) {
11040 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
11041 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
11042 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
11043 VAList = AndDst.getReg(0);
11050 LLT LLTTy = MRI.getType(Dst);
11053 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
11054 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
11059 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
11061 Align EltAlignment =
DL.getABITypeAlign(Ty);
11064 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
11066 MI.eraseFromParent();
11071 unsigned OpCode =
MI.getOpcode();
11072 assert((OpCode == TargetOpcode::G_SMULFIX ||
11073 OpCode == TargetOpcode::G_UMULFIX ||
11074 OpCode == TargetOpcode::G_SMULFIXSAT ||
11075 OpCode == TargetOpcode::G_UMULFIXSAT) &&
11076 "Operator must be either G_SMULFIX[SAT] or G_UMULFIX[SAT]!");
11077 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
11078 LLT Ty = MRI.getType(Dst);
11079 unsigned Scale =
MI.getOperand(3).getImm();
11081 bool Saturating = (OpCode == TargetOpcode::G_SMULFIXSAT ||
11082 OpCode == TargetOpcode::G_UMULFIXSAT);
11083 bool IsSigned = (OpCode == TargetOpcode::G_SMULFIX ||
11084 OpCode == TargetOpcode::G_SMULFIXSAT);
11086 if (!Saturating && Scale == 0) {
11088 MI.eraseFromParent();
11094 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
11117 MI.eraseFromParent();
11124 unsigned NumBits = Ty.getScalarSizeInBits();
11126 if (!Ty.isVector() && ValVRegAndVal) {
11135 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11158 auto &MF = *
MI.getParent()->getParent();
11163 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11164 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11167 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11168 const auto &DstMMO = **
MI.memoperands_begin();
11170 if (DstAlignCanChange) {
11173 Align NewAlign =
DL.getABITypeAlign(IRTy);
11174 if (NewAlign > Alignment) {
11183 MachineIRBuilder MIB(
MI);
11185 LLT LargestTy = MemOps[0];
11186 for (
unsigned i = 1; i < MemOps.
size(); i++)
11188 LargestTy = MemOps[i];
11200 LLT PtrTy = MRI.getType(Dst);
11201 unsigned DstOff = 0;
11202 unsigned Size = KnownLen;
11203 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11204 LLT Ty = MemOps[
I];
11207 if (TySize >
Size) {
11211 DstOff -= TySize -
Size;
11221 TLI.isTruncateFree(LargestVT, VT))
11222 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11235 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11238 MIB.buildStore(
Value, Ptr, *StoreMMO);
11243 MI.eraseFromParent();
11251 auto &MF = *
MI.getParent()->getParent();
11255 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11256 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11259 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11265 const auto &DstMMO = **
MI.memoperands_begin();
11266 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11268 if (DstAlignCanChange) {
11271 Align NewAlign =
DL.getABITypeAlign(IRTy);
11276 if (!
TRI->hasStackRealignment(MF))
11277 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11278 NewAlign = std::min(NewAlign, *StackAlign);
11280 if (NewAlign > Alignment) {
11289 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11291 MachineIRBuilder MIB(
MI);
11297 LLT SrcTy = MRI.getType(Src);
11298 LLT DstTy = MRI.getType(Dst);
11301 unsigned CurrOffset = 0;
11302 unsigned Size = KnownLen;
11303 for (
auto CopyTy : MemOps) {
11304 TypeSize TySize = CopyTy.getSizeInBytes();
11308 if (TySize >
Size) {
11309 unsigned Overlap = TySize -
Size;
11310 assert(Overlap < CurrOffset &&
11311 "overlapping memcpy load/store spans the whole region or more");
11312 CurrOffset -= Overlap;
11322 if (CurrOffset != 0) {
11324 MIB.buildConstant(
LLT::integer(SrcIndexSize), CurrOffset).getReg(0);
11325 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11327 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11331 if (CurrOffset != 0) {
11332 if (SrcIndexSize != DstIndexSize) {
11334 MIB.buildConstant(
LLT::integer(DstIndexSize), CurrOffset).getReg(0);
11336 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11338 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11339 CurrOffset += TySize;
11343 MI.eraseFromParent();
11351 auto &MF = *
MI.getParent()->getParent();
11355 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11356 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11359 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11360 const auto &DstMMO = **
MI.memoperands_begin();
11361 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11363 if (DstAlignCanChange) {
11366 Align NewAlign =
DL.getABITypeAlign(IRTy);
11371 if (!
TRI->hasStackRealignment(MF))
11372 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11373 NewAlign = std::min(NewAlign, *StackAlign);
11375 if (NewAlign > Alignment) {
11384 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11386 MachineIRBuilder MIB(
MI);
11390 unsigned CurrOffset = 0;
11391 unsigned Size = KnownLen;
11392 SmallVector<Register, 16> LoadVals;
11393 for (
auto CopyTy : MemOps) {
11394 TypeSize TySize = CopyTy.getSizeInBytes();
11398 if (TySize >
Size) {
11399 unsigned Overlap = TySize -
Size;
11400 assert(Overlap < CurrOffset &&
11401 "overlapping memmove load spans the whole region or more");
11402 CurrOffset -= Overlap;
11410 if (CurrOffset != 0) {
11411 LLT SrcTy = MRI.getType(Src);
11414 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11416 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11417 CurrOffset += TySize;
11423 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11424 LLT CopyTy = MemOps[
I];
11429 if (TySize >
Size) {
11430 unsigned Overlap = TySize -
Size;
11431 assert(Overlap < CurrOffset &&
11432 "overlapping memmove store spans the whole region or more");
11433 CurrOffset -= Overlap;
11440 if (CurrOffset != 0) {
11441 LLT DstTy = MRI.getType(Dst);
11444 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11446 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11447 CurrOffset += TySize;
11450 MI.eraseFromParent();
11457 const unsigned Opc =
MI.getOpcode();
11458 assert((
Opc == TargetOpcode::G_MEMCPY ||
11459 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11460 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11461 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11462 "Expected memcpy like instruction");
11464 if (KnownLen == 0) {
11465 MI.eraseFromParent();
11469 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11470 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11473 if (
Opc == TargetOpcode::G_MEMMOVE)
11474 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11476 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11477 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11487 bool DstAlignCanChange;
11488 std::vector<LLT> MemOps;
11490 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 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 unsigned getAtomicLibcallISDOpcode(unsigned Opc)
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.
static MVT getIntegerVT(unsigned BitWidth)
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.
AtomicOrdering getMergedOrdering() const
Return a single atomic ordering that is at least as strong as both the success and failure orderings ...
@ 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.
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ 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.
LLVM_ABI AtomicLibcall selectAtomicLibcall(const LibcallLoweringInfo &Libcalls, unsigned Opc, AtomicOrdering Order, MVT VT)
Lower to outline atomic libcall if outline atomics enabled, or to sync libcall otherwise.
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.