130static std::optional<bool>
134 unsigned Width = MemOffset2Idx.
size();
137 bool BigEndian =
true, LittleEndian =
true;
138 for (
unsigned MemOffset = 0; MemOffset < Width; ++ MemOffset) {
139 auto MemOffsetAndIdx = MemOffset2Idx.
find(MemOffset);
140 if (MemOffsetAndIdx == MemOffset2Idx.
end())
142 const int64_t Idx = MemOffsetAndIdx->second - LowestIdx;
143 assert(Idx >= 0 &&
"Expected non-negative byte offset?");
146 if (!BigEndian && !LittleEndian)
150 assert((BigEndian != LittleEndian) &&
151 "Pattern cannot be both big and little endian!");
158 assert(
LI &&
"Must have LegalizerInfo to query isLegal!");
186 return isLegal({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}}) &&
187 isLegal({TargetOpcode::G_CONSTANT, {EltTy}});
194 if (
MRI.constrainRegAttrs(ToReg, FromReg))
195 MRI.replaceRegWith(FromReg, ToReg);
197 Builder.buildCopy(FromReg, ToReg);
199 Observer.finishedChangingAllUsesOfReg();
214 unsigned ToOpcode)
const {
229 MRI.setRegBank(Reg, *RegBank);
240 if (
MI.getOpcode() != TargetOpcode::COPY)
250 MI.eraseFromParent();
255 assert(
MI.getOpcode() == TargetOpcode::G_FREEZE &&
"Invalid instruction");
261 if (!
MRI.hasOneNonDBGUse(OrigOp))
282 std::optional<MachineOperand> MaybePoisonOperand;
284 if (!Operand.isReg())
290 if (!MaybePoisonOperand)
291 MaybePoisonOperand = Operand;
300 if (!MaybePoisonOperand) {
305 B.buildCopy(
DstOp, OrigOp);
310 Register MaybePoisonOperandReg = MaybePoisonOperand->getReg();
311 LLT MaybePoisonOperandRegTy =
MRI.getType(MaybePoisonOperandReg);
314 {TargetOpcode::G_FREEZE, {MaybePoisonOperandRegTy}}))
322 auto Freeze =
B.buildFreeze(MaybePoisonOperandRegTy, MaybePoisonOperandReg);
333 assert(
MI.getOpcode() == TargetOpcode::G_CONCAT_VECTORS &&
334 "Invalid instruction");
346 if (!
MRI.hasOneNonDBGUse(Reg))
348 switch (Def->getOpcode()) {
349 case TargetOpcode::G_BUILD_VECTOR:
354 Ops.push_back(BuildVecMO.getReg());
356 case TargetOpcode::G_IMPLICIT_DEF: {
357 LLT OpType =
MRI.getType(Reg);
364 OpType.getScalarType() &&
365 "All undefs should have the same type");
368 for (
unsigned EltIdx = 0, EltEnd = OpType.getNumElements();
369 EltIdx != EltEnd; ++EltIdx)
370 Ops.push_back(
Undef->getOperand(0).getReg());
379 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
381 {TargetOpcode::G_BUILD_VECTOR, {DstTy,
MRI.getType(
Ops[0])}})) {
396 Register NewDstReg =
MRI.cloneVirtualRegister(DstReg);
409 MI.eraseFromParent();
418 if (!Unmerge || Unmerge->
getReg(0) != BV.getSourceReg(0))
423 LLT InputTy =
MRI.getType(BCSrc);
425 if (!InputTy.
isScalar() || BV.getNumSources() % Factor != 0)
430 if (!
isLegal({TargetOpcode::G_BUILD_VECTOR, {BVDstTy, InputTy}}))
434 for (
unsigned Idx = 0; Idx < BV.getNumSources(); Idx += Factor) {
450 Ops.push_back(BCSrc);
471 auto BV =
Builder.buildBuildVector(BVDstTy,
Ops);
472 Builder.buildBitcast(
MI.getOperand(0).getReg(), BV);
473 MI.eraseFromParent();
479 Register SrcVec1 = Shuffle.getSrc1Reg();
480 Register SrcVec2 = Shuffle.getSrc2Reg();
481 LLT EltTy =
MRI.getType(SrcVec1).getElementType();
482 int Width =
MRI.getType(SrcVec1).getNumElements();
484 auto Unmerge1 =
Builder.buildUnmerge(EltTy, SrcVec1);
485 auto Unmerge2 =
Builder.buildUnmerge(EltTy, SrcVec2);
489 for (
int Val : Shuffle.getMask()) {
492 else if (Val < Width)
493 Extracts.
push_back(Unmerge1.getReg(Val));
495 Extracts.
push_back(Unmerge2.getReg(Val - Width));
497 assert(Extracts.
size() > 0 &&
"Expected at least one element in the shuffle");
498 if (Extracts.
size() == 1)
499 Builder.buildCopy(
MI.getOperand(0).getReg(), Extracts[0]);
501 Builder.buildBuildVector(
MI.getOperand(0).getReg(), Extracts);
502 MI.eraseFromParent();
519 LLT ShuffleSrcTy1 =
MRI.getType(
MI.getOperand(1).getReg());
521 for (
unsigned i = 0; i < Mask.size(); i += ConcatSrcNumElt) {
525 for (
unsigned j = 1; j < ConcatSrcNumElt; j++) {
526 if (i + j >= Mask.size())
528 if (Mask[i + j] != -1)
532 {TargetOpcode::G_IMPLICIT_DEF, {ConcatSrcTy}}))
535 }
else if (Mask[i] % ConcatSrcNumElt == 0) {
536 for (
unsigned j = 1; j < ConcatSrcNumElt; j++) {
537 if (i + j >= Mask.size())
539 if (Mask[i + j] != Mask[i] +
static_cast<int>(j))
556 {TargetOpcode::G_CONCAT_VECTORS,
557 {
MRI.getType(
MI.getOperand(0).getReg()), ConcatSrcTy}}))
568 SrcTy =
MRI.getType(Reg);
570 assert(SrcTy.isValid() &&
"Unexpected full undef vector in concat combine");
577 UndefReg =
Builder.buildUndef(SrcTy).getReg(0);
583 Builder.buildConcatVectors(
MI.getOperand(0).getReg(),
Ops);
586 MI.eraseFromParent();
591 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
592 "Invalid instruction kind");
593 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
595 LLT SrcType =
MRI.getType(Src1);
597 unsigned DstNumElts = DstType.getNumElements();
598 unsigned SrcNumElts = SrcType.getNumElements();
615 if (DstNumElts < 2 * SrcNumElts)
620 if (DstNumElts % SrcNumElts != 0)
626 unsigned NumConcat = DstNumElts / SrcNumElts;
629 for (
unsigned i = 0; i != DstNumElts; ++i) {
636 if ((Idx % SrcNumElts != (i % SrcNumElts)) ||
637 (ConcatSrcs[i / SrcNumElts] >= 0 &&
638 ConcatSrcs[i / SrcNumElts] != (
int)(Idx / SrcNumElts)))
641 ConcatSrcs[i / SrcNumElts] = Idx / SrcNumElts;
648 for (
auto Src : ConcatSrcs) {
652 UndefReg =
Builder.buildUndef(SrcType).getReg(0);
654 Ops.push_back(UndefReg);
667 Register NewDstReg =
MRI.cloneVirtualRegister(DstReg);
675 MI.eraseFromParent();
684 const LLT TyForCandidate,
685 unsigned OpcodeForCandidate,
690 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
701 if (OpcodeForCandidate == TargetOpcode::G_ANYEXT &&
704 else if (CurrentUse.
ExtendOpcode == TargetOpcode::G_ANYEXT &&
705 OpcodeForCandidate != TargetOpcode::G_ANYEXT)
706 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
714 OpcodeForCandidate == TargetOpcode::G_ZEXT)
716 else if (CurrentUse.
ExtendOpcode == TargetOpcode::G_ZEXT &&
717 OpcodeForCandidate == TargetOpcode::G_SEXT)
718 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
727 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
738static void InsertInsnsWithoutSideEffectsBeforeUse(
750 InsertBB = PredBB->
getMBB();
755 if (InsertBB ==
DefMI.getParent()) {
757 Inserter(InsertBB, std::next(InsertPt), UseMO);
776 unsigned CandidateLoadOpc;
778 case TargetOpcode::G_ANYEXT:
779 CandidateLoadOpc = TargetOpcode::G_LOAD;
781 case TargetOpcode::G_SEXT:
782 CandidateLoadOpc = TargetOpcode::G_SEXTLOAD;
784 case TargetOpcode::G_ZEXT:
785 CandidateLoadOpc = TargetOpcode::G_ZEXTLOAD;
790 return CandidateLoadOpc;
807 LLT LoadValueTy =
MRI.getType(LoadReg);
829 unsigned PreferredOpcode =
831 ? TargetOpcode::G_ANYEXT
833 Preferred = {
LLT(), PreferredOpcode,
nullptr};
834 for (
auto &
UseMI :
MRI.use_nodbg_instructions(LoadReg)) {
835 if (
UseMI.getOpcode() == TargetOpcode::G_SEXT ||
836 UseMI.getOpcode() == TargetOpcode::G_ZEXT ||
837 (
UseMI.getOpcode() == TargetOpcode::G_ANYEXT)) {
838 const auto &MMO = LoadMI->
getMMO();
846 LLT UseTy =
MRI.getType(
UseMI.getOperand(0).getReg());
848 if (
LI->getAction({CandidateLoadOpc, {UseTy, SrcTy}, {MMDesc}})
852 Preferred = ChoosePreferredUse(
MI, Preferred,
853 MRI.getType(
UseMI.getOperand(0).getReg()),
863 assert(Preferred.Ty != LoadValueTy &&
"Extending to same type?");
881 if (PreviouslyEmitted) {
888 Builder.setInsertPt(*InsertIntoBB, InsertBefore);
889 Register NewDstReg =
MRI.cloneVirtualRegister(
MI.getOperand(0).getReg());
891 EmittedInsns[InsertIntoBB] = NewMI;
897 MI.setDesc(
Builder.getTII().get(LoadOpc));
904 for (
auto *UseMO :
Uses) {
910 UseMI->getOpcode() == TargetOpcode::G_ANYEXT) {
913 const LLT UseDstTy =
MRI.getType(UseDstReg);
914 if (UseDstReg != ChosenDstReg) {
915 if (Preferred.
Ty == UseDstTy) {
952 InsertInsnsWithoutSideEffectsBeforeUse(
Builder,
MI, *UseMO,
967 InsertInsnsWithoutSideEffectsBeforeUse(
Builder,
MI, *UseMO, InsertTruncAt);
970 MI.getOperand(0).setReg(ChosenDstReg);
976 assert(
MI.getOpcode() == TargetOpcode::G_AND);
987 if (
MRI.getType(Dst).isVector())
995 APInt MaskVal = MaybeMask->Value;
1010 LLT RegTy =
MRI.getType(LoadReg);
1013 unsigned MaskSizeBits = MaskVal.
countr_one();
1016 !
MRI.hasOneNonDBGUse(LoadReg))
1021 if (MaskSizeBits > LoadSizeBits)
1040 else if (LoadSizeBits > MaskSizeBits || LoadSizeBits ==
RegSize)
1045 {TargetOpcode::G_ZEXTLOAD, {RegTy,
MRI.getType(PtrReg)}, {MemDesc}}))
1049 B.setInstrAndDebugLoc(*LoadMI);
1050 auto &MF =
B.getMF();
1052 auto *NewMMO = MF.getMachineMemOperand(MMO, PtrInfo, MemDesc.
MemoryTy);
1053 B.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, Dst, PtrReg, *NewMMO);
1063 "shouldn't consider debug uses");
1071 if (DefOrUse ==
MBB.end())
1073 return &*DefOrUse == &
DefMI;
1079 "shouldn't consider debug uses");
1082 else if (
DefMI.getParent() !=
UseMI.getParent())
1089 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1093 if (
MRI.getType(SrcReg).isVector())
1098 LoadUser = TruncSrc;
1100 uint64_t SizeInBits =
MI.getOperand(2).getImm();
1105 auto LoadSizeBits = LoadMI->getMemSizeInBits();
1107 MRI.getType(TruncSrc).getSizeInBits() < LoadSizeBits.getValue())
1109 if (LoadSizeBits == SizeInBits)
1116 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1117 Builder.buildCopy(
MI.getOperand(0).getReg(),
MI.getOperand(1).getReg());
1118 MI.eraseFromParent();
1122 MachineInstr &
MI, std::tuple<Register, unsigned> &MatchInfo)
const {
1123 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1126 LLT RegTy =
MRI.getType(DstReg);
1139 uint64_t ExtFrom =
MI.getOperand(2).getImm();
1141 if (MemBits > ExtFrom && !
MRI.hasOneNonDBGUse(SrcReg))
1147 unsigned NewSizeBits = std::min(ExtFrom, MemBits);
1150 if (NewSizeBits < 8)
1163 else if (MemBits > NewSizeBits || MemBits == RegTy.
getSizeInBits())
1168 {TargetOpcode::G_SEXTLOAD, {RegTy,
MRI.getType(PtrReg)}, {MMDesc}}))
1171 MatchInfo = std::make_tuple(SrcReg, NewSizeBits);
1176 MachineInstr &
MI, std::tuple<Register, unsigned> &MatchInfo)
const {
1177 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1179 unsigned ScalarSizeBits;
1180 std::tie(LoadReg, ScalarSizeBits) = MatchInfo;
1189 auto &MMO = LoadDef->
getMMO();
1190 Builder.setInstrAndDebugLoc(*LoadDef);
1192 auto PtrInfo = MMO.getPointerInfo();
1193 auto *NewMMO = MF.getMachineMemOperand(&MMO, PtrInfo, ScalarSizeBits / 8);
1194 Builder.buildLoadInstr(TargetOpcode::G_SEXTLOAD,
MI.getOperand(0).getReg(),
1197 MI.eraseFromParent();
1208 auto *MF =
MI->getMF();
1215 AM.
BaseOffs = CstOff->getSExtValue();
1220 MF->getDataLayout(), AM,
1222 MF->getFunction().getContext()),
1223 MI->getMMO().getAddrSpace());
1228 case TargetOpcode::G_LOAD:
1229 return TargetOpcode::G_INDEXED_LOAD;
1230 case TargetOpcode::G_STORE:
1231 return TargetOpcode::G_INDEXED_STORE;
1232 case TargetOpcode::G_ZEXTLOAD:
1233 return TargetOpcode::G_INDEXED_ZEXTLOAD;
1234 case TargetOpcode::G_SEXTLOAD:
1235 return TargetOpcode::G_INDEXED_SEXTLOAD;
1241bool CombinerHelper::isIndexedLoadStoreLegal(
GLoadStore &LdSt)
const {
1251 if (IndexedOpc == TargetOpcode::G_INDEXED_STORE)
1252 OpTys = {PtrTy, Ty, Ty};
1254 OpTys = {Ty, PtrTy};
1256 LegalityQuery Q(IndexedOpc, OpTys, MemDescrs);
1262 cl::desc(
"Number of uses of a base pointer to check before it is no longer "
1263 "considered for post-indexing."));
1267 bool &RematOffset)
const {
1280 if (!isIndexedLoadStoreLegal(LdSt))
1291 unsigned NumUsesChecked = 0;
1304 if (StoredValDef == &
Use)
1307 Offset = PtrAdd->getOffsetReg();
1309 !TLI.isIndexingLegal(LdSt, PtrAdd->getBaseReg(),
Offset,
1317 RematOffset =
false;
1321 if (OffsetDef->
getOpcode() != TargetOpcode::G_CONSTANT)
1326 for (
auto &BasePtrUse :
MRI.use_nodbg_instructions(PtrAdd->getBaseReg())) {
1327 if (&BasePtrUse == PtrDef)
1333 if (BasePtrLdSt && BasePtrLdSt != &LdSt &&
1335 isIndexedLoadStoreLegal(*BasePtrLdSt))
1341 Register PtrAddDefReg = BasePtrUseDef->getReg(0);
1342 for (
auto &BaseUseUse :
MRI.use_nodbg_instructions(PtrAddDefReg)) {
1345 if (BaseUseUse.getParent() != LdSt.
getParent())
1357 Addr = PtrAdd->getReg(0);
1358 Base = PtrAdd->getBaseReg();
1373 MRI.hasOneNonDBGUse(Addr))
1380 if (!isIndexedLoadStoreLegal(LdSt))
1384 if (BaseDef->
getOpcode() == TargetOpcode::G_FRAME_INDEX)
1389 if (
Base == St->getValueReg())
1394 if (St->getValueReg() == Addr)
1399 for (
auto &AddrUse :
MRI.use_nodbg_instructions(Addr))
1400 if (AddrUse.getParent() != LdSt.
getParent())
1405 bool RealUse =
false;
1406 for (
auto &AddrUse :
MRI.use_nodbg_instructions(Addr)) {
1424 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT);
1434 assert(
MRI.getType(
MI.getOperand(0).getReg()) == VecEltTy);
1441 if (!LoadMI->isSimple())
1453 const unsigned MaxIter = 20;
1456 if (
II->isLoadFoldBarrier())
1458 if (Iter++ == MaxIter)
1474 int Elt = CVal->getZExtValue();
1487 Register VecPtr = LoadMI->getPointerReg();
1488 LLT PtrTy =
MRI.getType(VecPtr);
1496 {TargetOpcode::G_LOAD, {VecEltTy, PtrTy}, {MMDesc}}))
1519 B.buildLoad(Result, finalPtr, PtrInfo, Alignment);
1534 MatchInfo.
IsPre = findPreIndexCandidate(LdSt, MatchInfo.
Addr, MatchInfo.
Base,
1536 if (!MatchInfo.
IsPre &&
1537 !findPostIndexCandidate(LdSt, MatchInfo.
Addr, MatchInfo.
Base,
1547 unsigned Opcode =
MI.getOpcode();
1548 bool IsStore = Opcode == TargetOpcode::G_STORE;
1554 auto *OldCst =
MRI.getVRegDef(MatchInfo.
Offset);
1556 *OldCst->getOperand(1).getCImm());
1557 MatchInfo.
Offset = NewCst.getReg(0);
1560 auto MIB =
Builder.buildInstr(NewOpcode);
1562 MIB.addDef(MatchInfo.
Addr);
1563 MIB.addUse(
MI.getOperand(0).getReg());
1565 MIB.addDef(
MI.getOperand(0).getReg());
1566 MIB.addDef(MatchInfo.
Addr);
1569 MIB.addUse(MatchInfo.
Base);
1570 MIB.addUse(MatchInfo.
Offset);
1571 MIB.addImm(MatchInfo.
IsPre);
1572 MIB->cloneMemRefs(*
MI.getMF(),
MI);
1573 MI.eraseFromParent();
1581 unsigned Opcode =
MI.getOpcode();
1582 bool IsDiv, IsSigned;
1587 case TargetOpcode::G_SDIV:
1588 case TargetOpcode::G_UDIV: {
1590 IsSigned = Opcode == TargetOpcode::G_SDIV;
1593 case TargetOpcode::G_SREM:
1594 case TargetOpcode::G_UREM: {
1596 IsSigned = Opcode == TargetOpcode::G_SREM;
1602 unsigned DivOpcode, RemOpcode, DivremOpcode;
1604 DivOpcode = TargetOpcode::G_SDIV;
1605 RemOpcode = TargetOpcode::G_SREM;
1606 DivremOpcode = TargetOpcode::G_SDIVREM;
1608 DivOpcode = TargetOpcode::G_UDIV;
1609 RemOpcode = TargetOpcode::G_UREM;
1610 DivremOpcode = TargetOpcode::G_UDIVREM;
1628 for (
auto &
UseMI :
MRI.use_nodbg_instructions(Src1)) {
1629 if (
MI.getParent() ==
UseMI.getParent() &&
1630 ((IsDiv &&
UseMI.getOpcode() == RemOpcode) ||
1631 (!IsDiv &&
UseMI.getOpcode() == DivOpcode)) &&
1644 unsigned Opcode =
MI.getOpcode();
1645 assert(OtherMI &&
"OtherMI shouldn't be empty.");
1648 if (Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_UDIV) {
1649 DestDivReg =
MI.getOperand(0).getReg();
1653 DestRemReg =
MI.getOperand(0).getReg();
1657 Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_SREM;
1664 Builder.setInstrAndDebugLoc(*FirstInst);
1666 Builder.buildInstr(IsSigned ? TargetOpcode::G_SDIVREM
1667 : TargetOpcode::G_UDIVREM,
1668 {DestDivReg, DestRemReg},
1670 MI.eraseFromParent();
1676 assert(
MI.getOpcode() == TargetOpcode::G_BR);
1693 if (BrIt ==
MBB->begin())
1695 assert(std::next(BrIt) ==
MBB->end() &&
"expected G_BR to be a terminator");
1697 BrCond = &*std::prev(BrIt);
1698 if (BrCond->
getOpcode() != TargetOpcode::G_BRCOND)
1704 return BrCondTarget !=
MI.getOperand(0).getMBB() &&
1705 MBB->isLayoutSuccessor(BrCondTarget);
1711 Builder.setInstrAndDebugLoc(*BrCond);
1716 auto True =
Builder.buildConstant(
1722 MI.getOperand(0).setMBB(FallthroughBB);
1735 unsigned MaxLen)
const {
1736 auto &[Dst, Src, KnownLen, Alignment, DstAlignCanChange, MemOps] = MatchInfo;
1738 DstAlignCanChange, MemOps);
1743 auto &[Dst, Src, KnownLen, Alignment, DstAlignCanChange, MemOps] = MatchInfo;
1748 DstAlignCanChange, MemOps) ==
1750 assert(
Changed &&
"expected memcpy-family instruction to lower");
1755 unsigned MaxLen)
const {
1767 switch (
MI.getOpcode()) {
1770 case TargetOpcode::G_FNEG: {
1771 Result.changeSign();
1774 case TargetOpcode::G_FABS: {
1778 case TargetOpcode::G_FCEIL:
1781 case TargetOpcode::G_FFLOOR:
1784 case TargetOpcode::G_INTRINSIC_TRUNC:
1787 case TargetOpcode::G_INTRINSIC_ROUND:
1790 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
1793 case TargetOpcode::G_FRINT:
1794 case TargetOpcode::G_FNEARBYINT:
1798 case TargetOpcode::G_FPEXT:
1799 case TargetOpcode::G_FPTRUNC: {
1806 case TargetOpcode::G_FSQRT: {
1810 Result =
APFloat(sqrt(Result.convertToDouble()));
1813 case TargetOpcode::G_FLOG2: {
1833 Builder.buildFConstant(
MI.getOperand(0), *NewCst);
1834 MI.eraseFromParent();
1845 if (
MI.getOpcode() != TargetOpcode::G_PTR_ADD)
1868 Type *AccessTy =
nullptr;
1869 auto &MF = *
MI.getMF();
1870 for (
auto &
UseMI :
MRI.use_nodbg_instructions(
MI.getOperand(0).getReg())) {
1873 MF.getFunction().getContext());
1878 APInt CombinedImm = MaybeImmVal->Value + MaybeImm2Val->Value;
1883 AMOld.
BaseOffs = MaybeImmVal->Value.getSExtValue();
1885 unsigned AS =
MRI.getType(Add2).getAddressSpace();
1886 const auto &TLI = *MF.getSubtarget().getTargetLowering();
1887 if (TLI.isLegalAddressingMode(MF.getDataLayout(), AMOld, AccessTy, AS) &&
1888 !TLI.isLegalAddressingMode(MF.getDataLayout(), AMNew, AccessTy, AS))
1897 unsigned PtrAddFlags =
MI.getFlags();
1913 MatchInfo.
Flags = Flags;
1919 assert(
MI.getOpcode() == TargetOpcode::G_PTR_ADD &&
"Expected G_PTR_ADD");
1921 LLT OffsetTy =
MRI.getType(
MI.getOperand(2).getReg());
1925 MI.getOperand(1).setReg(MatchInfo.
Base);
1926 MI.getOperand(2).setReg(NewOffset.getReg(0));
1940 unsigned Opcode =
MI.getOpcode();
1941 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
1942 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_SSHLSAT ||
1943 Opcode == TargetOpcode::G_USHLSAT) &&
1944 "Expected G_SHL, G_ASHR, G_LSHR, G_SSHLSAT or G_USHLSAT");
1964 (MaybeImmVal->Value.getZExtValue() + MaybeImm2Val->Value).getZExtValue();
1969 if (Opcode == TargetOpcode::G_USHLSAT &&
1970 MatchInfo.
Imm >=
MRI.getType(Shl2).getScalarSizeInBits())
1978 unsigned Opcode =
MI.getOpcode();
1979 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
1980 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_SSHLSAT ||
1981 Opcode == TargetOpcode::G_USHLSAT) &&
1982 "Expected G_SHL, G_ASHR, G_LSHR, G_SSHLSAT or G_USHLSAT");
1984 LLT Ty =
MRI.getType(
MI.getOperand(1).getReg());
1985 unsigned const ScalarSizeInBits = Ty.getScalarSizeInBits();
1986 auto Imm = MatchInfo.
Imm;
1988 if (
Imm >= ScalarSizeInBits) {
1990 if (Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR) {
1991 Builder.buildConstant(
MI.getOperand(0), 0);
1992 MI.eraseFromParent();
1997 Imm = ScalarSizeInBits - 1;
2000 LLT ImmTy =
MRI.getType(
MI.getOperand(2).getReg());
2003 MI.getOperand(1).setReg(MatchInfo.
Reg);
2004 MI.getOperand(2).setReg(NewImm);
2020 unsigned ShiftOpcode =
MI.getOpcode();
2021 assert((ShiftOpcode == TargetOpcode::G_SHL ||
2022 ShiftOpcode == TargetOpcode::G_ASHR ||
2023 ShiftOpcode == TargetOpcode::G_LSHR ||
2024 ShiftOpcode == TargetOpcode::G_USHLSAT ||
2025 ShiftOpcode == TargetOpcode::G_SSHLSAT) &&
2026 "Expected G_SHL, G_ASHR, G_LSHR, G_USHLSAT and G_SSHLSAT");
2029 Register LogicDest =
MI.getOperand(1).getReg();
2030 if (!
MRI.hasOneNonDBGUse(LogicDest))
2036 unsigned LogicOpcode = LogicMI->
getOpcode();
2037 if (LogicOpcode != TargetOpcode::G_AND && LogicOpcode != TargetOpcode::G_OR &&
2038 LogicOpcode != TargetOpcode::G_XOR)
2042 const Register C1 =
MI.getOperand(2).getReg();
2044 if (!MaybeImmVal || MaybeImmVal->Value == 0)
2047 const uint64_t C1Val = MaybeImmVal->Value.getZExtValue();
2049 auto matchFirstShift = [&](
const MachineInstr *
MI, uint64_t &ShiftVal) {
2051 if (
MI->getOpcode() != ShiftOpcode ||
2052 !
MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()))
2061 ShiftVal = MaybeImmVal->Value.getSExtValue();
2075 if (matchFirstShift(LogicMIOp1, C0Val)) {
2077 MatchInfo.
Shift2 = LogicMIOp1;
2078 }
else if (matchFirstShift(LogicMIOp2, C0Val)) {
2080 MatchInfo.
Shift2 = LogicMIOp2;
2084 MatchInfo.
ValSum = C0Val + C1Val;
2087 if (MatchInfo.
ValSum >=
MRI.getType(LogicDest).getScalarSizeInBits())
2090 MatchInfo.
Logic = LogicMI;
2096 unsigned Opcode =
MI.getOpcode();
2097 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
2098 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_USHLSAT ||
2099 Opcode == TargetOpcode::G_SSHLSAT) &&
2100 "Expected G_SHL, G_ASHR, G_LSHR, G_USHLSAT and G_SSHLSAT");
2102 LLT ShlType =
MRI.getType(
MI.getOperand(2).getReg());
2103 LLT DestType =
MRI.getType(
MI.getOperand(0).getReg());
2109 Builder.buildInstr(Opcode, {DestType}, {Shift1Base, Const}).
getReg(0);
2118 Register Shift2Const =
MI.getOperand(2).getReg();
2120 .buildInstr(Opcode, {DestType},
2130 MI.eraseFromParent();
2135 assert(
MI.getOpcode() == TargetOpcode::G_SHL &&
"Expected G_SHL");
2160 LLT SrcTy =
MRI.getType(SrcReg);
2162 auto S1 =
B.buildShl(SrcTy,
X, ShiftReg);
2163 auto S2 =
B.buildShl(SrcTy, C1, ShiftReg);
2164 B.buildInstr(SrcOpc, {DstReg}, {
S1, S2});
2172 assert(
MI.getOpcode() == TargetOpcode::G_LSHR &&
"Expected a G_LSHR");
2176 unsigned OpSizeInBits =
MRI.getType(N0).getScalarSizeInBits();
2191 LLT InnerShiftTy =
MRI.getType(InnerShift);
2193 if ((N1C + N001C).ult(InnerShiftSize)) {
2199 if ((N001C + OpSizeInBits) == InnerShiftSize)
2201 if (
MRI.hasOneUse(N0) &&
MRI.hasOneUse(InnerShift)) {
2202 MatchInfo.
Mask =
true;
2212 assert(
MI.getOpcode() == TargetOpcode::G_LSHR &&
"Expected a G_LSHR");
2219 if (MatchInfo.
Mask ==
true) {
2227 Builder.buildTrunc(Dst, Shift);
2228 MI.eraseFromParent();
2232 unsigned &ShiftVal)
const {
2233 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
"Expected a G_MUL");
2239 ShiftVal = MaybeImmVal->Value.exactLogBase2();
2240 return (
static_cast<int32_t
>(ShiftVal) != -1);
2244 unsigned &ShiftVal)
const {
2245 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
"Expected a G_MUL");
2247 LLT ShiftTy =
MRI.getType(
MI.getOperand(0).getReg());
2250 MI.setDesc(MIB.
getTII().
get(TargetOpcode::G_SHL));
2251 MI.getOperand(2).setReg(ShiftCst.getReg(0));
2272 auto NegCst =
B.buildConstant(Ty, -
Imm);
2274 MI.setDesc(
B.getTII().get(TargetOpcode::G_ADD));
2275 MI.getOperand(2).setReg(NegCst.getReg(0));
2277 if (
Imm.isMinSignedValue())
2287 assert(
MI.getOpcode() == TargetOpcode::G_SHL &&
VT);
2301 if (!MaybeShiftAmtVal)
2305 LLT SrcTy =
MRI.getType(ExtSrc);
2315 int64_t ShiftAmt = MaybeShiftAmtVal->getSExtValue();
2316 MatchData.
Reg = ExtSrc;
2317 MatchData.
Imm = ShiftAmt;
2319 unsigned MinLeadingZeros =
VT->getKnownZeroes(ExtSrc).countl_one();
2320 unsigned SrcTySize =
MRI.getType(ExtSrc).getScalarSizeInBits();
2321 return MinLeadingZeros >= ShiftAmt && ShiftAmt < SrcTySize;
2327 int64_t ShiftAmtVal = MatchData.
Imm;
2329 LLT ExtSrcTy =
MRI.getType(ExtSrcReg);
2330 auto ShiftAmt =
Builder.buildConstant(ExtSrcTy, ShiftAmtVal);
2332 Builder.buildShl(ExtSrcTy, ExtSrcReg, ShiftAmt,
MI.getFlags());
2333 Builder.buildZExt(
MI.getOperand(0), NarrowShift);
2334 MI.eraseFromParent();
2341 for (
unsigned I = 0;
I <
Merge.getNumSources(); ++
I)
2345 if (!Unmerge || Unmerge->getNumDefs() !=
Merge.getNumSources())
2348 for (
unsigned I = 0;
I < MergedValues.
size(); ++
I)
2349 if (MergedValues[
I] != Unmerge->getReg(
I))
2352 MatchInfo = Unmerge->getSourceReg();
2366 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2367 "Expected an unmerge");
2376 LLT SrcMergeTy =
MRI.getType(SrcInstr->getSourceReg(0));
2377 LLT Dst0Ty =
MRI.getType(Unmerge.getReg(0));
2379 if (SrcMergeTy != Dst0Ty && !SameSize)
2383 for (
unsigned Idx = 0; Idx < SrcInstr->getNumSources(); ++Idx)
2384 Operands.push_back(SrcInstr->getSourceReg(Idx));
2390 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2391 "Expected an unmerge");
2393 "Not enough operands to replace all defs");
2394 unsigned NumElems =
MI.getNumOperands() - 1;
2397 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
2398 bool CanReuseInputDirectly = DstTy == SrcTy;
2399 for (
unsigned Idx = 0; Idx < NumElems; ++Idx) {
2400 Register DstReg =
MI.getOperand(Idx).getReg();
2405 const auto &DstCB =
MRI.getRegClassOrRegBank(DstReg);
2406 if (!DstCB.isNull() && DstCB !=
MRI.getRegClassOrRegBank(SrcReg)) {
2407 SrcReg =
Builder.buildCopy(
MRI.getType(SrcReg), SrcReg).getReg(0);
2408 MRI.setRegClassOrRegBank(SrcReg, DstCB);
2411 if (CanReuseInputDirectly)
2414 Builder.buildCast(DstReg, SrcReg);
2416 MI.eraseFromParent();
2421 unsigned SrcIdx =
MI.getNumOperands() - 1;
2422 Register SrcReg =
MI.getOperand(SrcIdx).getReg();
2428 LLT Dst0Ty =
MRI.getType(
MI.getOperand(0).getReg());
2431 for (
unsigned Idx = 0; Idx != SrcIdx; ++Idx) {
2433 Val = Val.
lshr(ShiftAmt);
2441 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2442 "Expected an unmerge");
2444 "Not enough operands to replace all defs");
2445 unsigned NumElems =
MI.getNumOperands() - 1;
2446 for (
unsigned Idx = 0; Idx < NumElems; ++Idx) {
2447 Register DstReg =
MI.getOperand(Idx).getReg();
2448 Builder.buildConstant(DstReg, Csts[Idx]);
2451 MI.eraseFromParent();
2457 unsigned SrcIdx =
MI.getNumOperands() - 1;
2458 Register SrcReg =
MI.getOperand(SrcIdx).getReg();
2460 unsigned NumElems =
MI.getNumOperands() - 1;
2461 for (
unsigned Idx = 0; Idx < NumElems; ++Idx) {
2462 Register DstReg =
MI.getOperand(Idx).getReg();
2463 B.buildUndef(DstReg);
2471 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2472 "Expected an unmerge");
2473 if (!
MRI.getType(
MI.getOperand(0).getReg()).isScalar() ||
2474 !
MRI.getType(
MI.getOperand(
MI.getNumDefs()).getReg()).isScalar())
2477 for (
unsigned Idx = 1, EndIdx =
MI.getNumDefs(); Idx != EndIdx; ++Idx) {
2478 if (!
MRI.use_nodbg_empty(
MI.getOperand(Idx).getReg()))
2486 Register SrcReg =
MI.getOperand(
MI.getNumDefs()).getReg();
2487 Register Dst0Reg =
MI.getOperand(0).getReg();
2488 Builder.buildTrunc(Dst0Reg, SrcReg);
2489 MI.eraseFromParent();
2493 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2494 "Expected an unmerge");
2495 Register Dst0Reg =
MI.getOperand(0).getReg();
2496 LLT Dst0Ty =
MRI.getType(Dst0Reg);
2502 Register SrcReg =
MI.getOperand(
MI.getNumDefs()).getReg();
2503 LLT SrcTy =
MRI.getType(SrcReg);
2504 if (SrcTy.isVector())
2514 LLT ZExtSrcTy =
MRI.getType(ZExtSrcReg);
2519 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2520 "Expected an unmerge");
2522 Register Dst0Reg =
MI.getOperand(0).getReg();
2527 LLT Dst0Ty =
MRI.getType(Dst0Reg);
2528 LLT ZExtSrcTy =
MRI.getType(ZExtSrcReg);
2531 Builder.buildZExt(Dst0Reg, ZExtSrcReg);
2534 "ZExt src doesn't fit in destination");
2539 for (
unsigned Idx = 1, EndIdx =
MI.getNumDefs(); Idx != EndIdx; ++Idx) {
2541 ZeroReg =
Builder.buildConstant(Dst0Ty, 0).getReg(0);
2544 MI.eraseFromParent();
2548 unsigned TargetShiftSize,
2549 unsigned &ShiftVal)
const {
2550 assert((
MI.getOpcode() == TargetOpcode::G_SHL ||
2551 MI.getOpcode() == TargetOpcode::G_LSHR ||
2552 MI.getOpcode() == TargetOpcode::G_ASHR) &&
"Expected a shift");
2554 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
2559 unsigned Size = Ty.getSizeInBits();
2560 if (
Size <= TargetShiftSize)
2568 ShiftVal = MaybeImmVal->Value.getSExtValue();
2569 return ShiftVal >=
Size / 2 && ShiftVal <
Size;
2576 LLT Ty =
MRI.getType(SrcReg);
2577 unsigned Size = Ty.getSizeInBits();
2578 unsigned HalfSize =
Size / 2;
2579 assert(ShiftVal >= HalfSize);
2583 auto Unmerge =
Builder.buildUnmerge(HalfTy, SrcReg);
2584 unsigned NarrowShiftAmt = ShiftVal - HalfSize;
2586 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
2587 Register Narrowed = Unmerge.getReg(1);
2594 if (NarrowShiftAmt != 0) {
2595 Narrowed =
Builder.buildLShr(HalfTy, Narrowed,
2596 Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
2599 auto Zero =
Builder.buildConstant(HalfTy, 0);
2600 Builder.buildMergeLikeInstr(DstReg, {Narrowed, Zero});
2601 }
else if (
MI.getOpcode() == TargetOpcode::G_SHL) {
2602 Register Narrowed = Unmerge.getReg(0);
2607 if (NarrowShiftAmt != 0) {
2608 Narrowed =
Builder.buildShl(HalfTy, Narrowed,
2609 Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
2612 auto Zero =
Builder.buildConstant(HalfTy, 0);
2613 Builder.buildMergeLikeInstr(DstReg, {Zero, Narrowed});
2615 assert(
MI.getOpcode() == TargetOpcode::G_ASHR);
2617 HalfTy, Unmerge.getReg(1),
2618 Builder.buildConstant(HalfTy, HalfSize - 1));
2620 if (ShiftVal == HalfSize) {
2623 Builder.buildMergeLikeInstr(DstReg, {Unmerge.getReg(1),
Hi});
2624 }
else if (ShiftVal ==
Size - 1) {
2632 HalfTy, Unmerge.getReg(1),
2633 Builder.buildConstant(HalfTy, ShiftVal - HalfSize));
2641 MI.eraseFromParent();
2657 assert(
MI.getOpcode() == TargetOpcode::G_INTTOPTR &&
"Expected a G_INTTOPTR");
2659 LLT DstTy =
MRI.getType(DstReg);
2667 assert(
MI.getOpcode() == TargetOpcode::G_INTTOPTR &&
"Expected a G_INTTOPTR");
2669 Builder.buildCopy(DstReg, Reg);
2670 MI.eraseFromParent();
2675 assert(
MI.getOpcode() == TargetOpcode::G_PTRTOINT &&
"Expected a G_PTRTOINT");
2677 Builder.buildZExtOrTrunc(DstReg, Reg);
2678 MI.eraseFromParent();
2683 assert(
MI.getOpcode() == TargetOpcode::G_ADD);
2686 LLT IntTy =
MRI.getType(LHS);
2690 PtrReg.second =
false;
2691 for (
Register SrcReg : {LHS, RHS}) {
2695 LLT PtrTy =
MRI.getType(PtrReg.first);
2700 PtrReg.second =
true;
2712 const bool DoCommute = PtrReg.second;
2717 LLT PtrTy =
MRI.getType(LHS);
2719 auto PtrAdd =
Builder.buildPtrAdd(PtrTy, LHS, RHS);
2720 Builder.buildPtrToInt(Dst, PtrAdd);
2721 MI.eraseFromParent();
2725 APInt &NewCst)
const {
2727 Register LHS = PtrAdd.getBaseReg();
2728 Register RHS = PtrAdd.getOffsetReg();
2734 auto DstTy =
MRI.getType(PtrAdd.getReg(0));
2737 NewCst += RHSCst->
sextOrTrunc(DstTy.getSizeInBits());
2746 APInt &NewCst)
const {
2750 Builder.buildConstant(Dst, NewCst);
2751 PtrAdd.eraseFromParent();
2756 assert(
MI.getOpcode() == TargetOpcode::G_ANYEXT &&
"Expected a G_ANYEXT");
2761 SrcReg = OriginalSrcReg;
2762 LLT DstTy =
MRI.getType(DstReg);
2770 assert(
MI.getOpcode() == TargetOpcode::G_ZEXT &&
"Expected a G_ZEXT");
2773 LLT DstTy =
MRI.getType(DstReg);
2778 unsigned SrcSize =
MRI.getType(SrcReg).getScalarSizeInBits();
2779 return VT->getKnownBits(Reg).countMinLeadingZeros() >= DstSize - SrcSize;
2789 if (ShiftSize > 32 && TruncSize < 32)
2802 MachineInstr &
MI, std::pair<MachineInstr *, LLT> &MatchInfo)
const {
2803 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC &&
"Expected a G_TRUNC");
2807 if (!
MRI.hasOneNonDBGUse(SrcReg))
2810 LLT SrcTy =
MRI.getType(SrcReg);
2811 LLT DstTy =
MRI.getType(DstReg);
2820 case TargetOpcode::G_SHL: {
2829 case TargetOpcode::G_LSHR:
2830 case TargetOpcode::G_ASHR: {
2836 for (
auto &
User :
MRI.use_instructions(DstReg))
2837 if (
User.getOpcode() == TargetOpcode::G_STORE)
2841 if (NewShiftTy == SrcTy)
2855 {NewShiftTy, TL.getPreferredShiftAmountTy(NewShiftTy)}}))
2858 MatchInfo = std::make_pair(SrcMI, NewShiftTy);
2863 MachineInstr &
MI, std::pair<MachineInstr *, LLT> &MatchInfo)
const {
2865 LLT NewShiftTy = MatchInfo.second;
2868 LLT DstTy =
MRI.getType(Dst);
2872 ShiftSrc =
Builder.buildTrunc(NewShiftTy, ShiftSrc).getReg(0);
2875 LLT PrefShiftTy = TL.getPreferredShiftAmountTy(NewShiftTy);
2876 if (
MRI.getType(ShiftAmt) != PrefShiftTy)
2877 ShiftAmt =
Builder.buildZExtOrTrunc(PrefShiftTy, ShiftAmt).getReg(0);
2881 .buildInstr(ShiftMI->
getOpcode(), {NewShiftTy}, {ShiftSrc, ShiftAmt})
2884 if (NewShiftTy == DstTy)
2887 Builder.buildTrunc(Dst, NewShift);
2894 return MO.isReg() &&
2895 getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
2901 return !MO.isReg() ||
2902 getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
2907 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
2909 return all_of(Mask, [](
int Elt) {
return Elt < 0; });
2913 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
2914 return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
MI.getOperand(0).getReg(),
2919 assert(
MI.getOpcode() == TargetOpcode::G_SELECT);
2920 return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
MI.getOperand(1).getReg(),
2926 assert((
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT ||
2927 MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT) &&
2928 "Expected an insert/extract element op");
2929 LLT VecTy =
MRI.getType(
MI.getOperand(1).getReg());
2934 MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
2942 unsigned &OpIdx)
const {
2947 OpIdx = Cst->isZero() ? 3 : 2;
2992 if (I1->mayLoadOrStore() && !I1->isDereferenceableInvariantLoad())
3019 return MO.isReg() && MO.getReg().isPhysical();
3029 return I1->isIdenticalTo(*I2);
3037 if (
Builder.getTII().produceSameValue(*I1, *I2, &
MRI)) {
3044 return I1->findRegisterDefOperandIdx(InstAndDef1->Reg,
nullptr) ==
3055 return MaybeCst && MaybeCst->getBitWidth() <= 64 &&
3056 MaybeCst->getSExtValue() ==
C;
3063 std::optional<FPValueAndVReg> MaybeCst;
3067 return MaybeCst->Value.isExactlyValue(
C);
3071 unsigned OpIdx)
const {
3072 assert(
MI.getNumExplicitDefs() == 1 &&
"Expected one explicit def?");
3074 Register Replacement =
MI.getOperand(OpIdx).getReg();
3077 MI.eraseFromParent();
3082 assert(
MI.getNumExplicitDefs() == 1 &&
"Expected one explicit def?");
3086 MI.eraseFromParent();
3090 unsigned ConstIdx)
const {
3091 Register ConstReg =
MI.getOperand(ConstIdx).getReg();
3092 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
3104 assert((
MI.getOpcode() == TargetOpcode::G_FSHL ||
3105 MI.getOpcode() == TargetOpcode::G_FSHR) &&
3106 "This is not a funnel shift operation");
3108 Register ConstReg =
MI.getOperand(3).getReg();
3109 LLT ConstTy =
MRI.getType(ConstReg);
3110 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
3113 assert((VRegAndVal) &&
"Value is not a constant");
3116 APInt NewConst = VRegAndVal->Value.
urem(
3121 MI.getOpcode(), {MI.getOperand(0)},
3122 {MI.getOperand(1), MI.getOperand(2), NewConstInstr.getReg(0)});
3124 MI.eraseFromParent();
3128 assert(
MI.getOpcode() == TargetOpcode::G_SELECT);
3142 unsigned OpIdx)
const {
3144 return MO.
isReg() &&
3155 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3157 MI.eraseFromParent();
3162 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3164 MI.eraseFromParent();
3168 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3170 MI.eraseFromParent();
3175 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3177 MI.eraseFromParent();
3181 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3183 MI.eraseFromParent();
3187 MachineInstr &
MI, std::tuple<Register, Register> &MatchInfo)
const {
3190 Register &NewLHS = std::get<0>(MatchInfo);
3191 Register &NewRHS = std::get<1>(MatchInfo);
3199 NewLHS = MaybeNewLHS;
3203 return CheckFold(LHS, RHS) || CheckFold(RHS, LHS);
3208 assert(
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT &&
3211 LLT DstTy =
MRI.getType(DstReg);
3220 if (
MRI.hasOneUse(DstReg) &&
MRI.use_instr_begin(DstReg)->getOpcode() ==
3221 TargetOpcode::G_INSERT_VECTOR_ELT)
3227 MatchInfo.
resize(NumElts);
3231 if (IntImm >= NumElts || IntImm < 0)
3233 if (!MatchInfo[IntImm])
3234 MatchInfo[IntImm] = TmpReg;
3238 if (CurrInst->
getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
3240 if (TmpInst->
getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
3249 return TmpInst->
getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
3256 auto GetUndef = [&]() {
3259 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
3267 Builder.buildBuildVector(
MI.getOperand(0).getReg(), MatchInfo);
3268 MI.eraseFromParent();
3272 MachineInstr &
MI, std::tuple<Register, Register> &MatchInfo)
const {
3274 std::tie(SubLHS, SubRHS) = MatchInfo;
3275 Builder.buildSub(
MI.getOperand(0).getReg(), SubLHS, SubRHS);
3276 MI.eraseFromParent();
3289 unsigned InnerOpc = InnerDef->
getOpcode();
3290 if (InnerOpc != TargetOpcode::G_ADD && InnerOpc != TargetOpcode::G_SUB)
3314 if (!TryMatch(InnerLHS, InnerRHS) &&
3315 !(InnerOpc == TargetOpcode::G_ADD && TryMatch(InnerRHS, InnerLHS)))
3319 unsigned FlippedOpc = (InnerOpc == TargetOpcode::G_ADD) ? TargetOpcode::G_SUB
3320 : TargetOpcode::G_ADD;
3323 MatchInfo = [=](MachineIRBuilder &
Builder) {
3324 auto NewInner =
Builder.buildInstr(FlippedOpc, {Ty}, {
B,
C});
3325 auto NewNot =
Builder.buildNot(Ty, NewInner);
3326 Builder.buildInstr(RootOpc, {Dst}, {
A, NewNot});
3338 unsigned RootOpc =
MI.getOpcode();
3340 LLT Ty =
MRI.getType(Dst);
3345 return matchBinopWithNegInner(LHS, RHS, RootOpc, Dst, Ty, MatchInfo) ||
3346 matchBinopWithNegInner(RHS, LHS, RootOpc, Dst, Ty, MatchInfo);
3357 unsigned LogicOpcode =
MI.getOpcode();
3358 assert(LogicOpcode == TargetOpcode::G_AND ||
3359 LogicOpcode == TargetOpcode::G_OR ||
3360 LogicOpcode == TargetOpcode::G_XOR);
3367 if (!
MRI.hasOneNonDBGUse(LHSReg) || !
MRI.hasOneNonDBGUse(RHSReg))
3373 if (!LeftHandInst || !RightHandInst)
3375 unsigned HandOpcode = LeftHandInst->
getOpcode();
3376 if (HandOpcode != RightHandInst->
getOpcode())
3390 if (!XTy.
isValid() || XTy != YTy)
3395 switch (HandOpcode) {
3398 case TargetOpcode::G_ANYEXT:
3399 case TargetOpcode::G_SEXT:
3400 case TargetOpcode::G_ZEXT: {
3404 case TargetOpcode::G_TRUNC: {
3409 LLT DstTy =
MRI.getType(Dst);
3418 case TargetOpcode::G_AND:
3419 case TargetOpcode::G_ASHR:
3420 case TargetOpcode::G_LSHR:
3421 case TargetOpcode::G_SHL: {
3426 ExtraHandOpSrcReg = ZOp.
getReg();
3437 auto NewLogicDst =
MRI.createGenericVirtualRegister(XTy);
3448 if (ExtraHandOpSrcReg.
isValid())
3460 "Expected at least one instr to build?");
3462 assert(InstrToBuild.Opcode &&
"Expected a valid opcode?");
3463 assert(InstrToBuild.OperandFns.size() &&
"Expected at least one operand?");
3465 for (
auto &OperandFn : InstrToBuild.OperandFns)
3468 MI.eraseFromParent();
3472 MachineInstr &
MI, std::tuple<Register, int64_t> &MatchInfo)
const {
3473 assert(
MI.getOpcode() == TargetOpcode::G_ASHR);
3474 int64_t ShlCst, AshrCst;
3480 if (ShlCst != AshrCst)
3483 {TargetOpcode::G_SEXT_INREG,
3486 {
MRI.getType(Src).getScalarSizeInBits() - ShlCst}}))
3488 MatchInfo = std::make_tuple(Src, ShlCst);
3493 MachineInstr &
MI, std::tuple<Register, int64_t> &MatchInfo)
const {
3494 assert(
MI.getOpcode() == TargetOpcode::G_ASHR);
3497 std::tie(Src, ShiftAmt) = MatchInfo;
3498 unsigned Size =
MRI.getType(Src).getScalarSizeInBits();
3499 Builder.buildSExtInReg(
MI.getOperand(0).getReg(), Src,
Size - ShiftAmt);
3500 MI.eraseFromParent();
3507 assert(
MI.getOpcode() == TargetOpcode::G_AND);
3510 LLT Ty =
MRI.getType(Dst);
3522 B.buildAnd(Dst, R,
B.buildConstant(Ty, C1 & C2));
3525 auto Zero =
B.buildConstant(Ty, 0);
3548 assert(
MI.getOpcode() == TargetOpcode::G_AND);
3572 (LHSBits.
Zero | RHSBits.
One).isAllOnes()) {
3579 (LHSBits.
One | RHSBits.
Zero).isAllOnes()) {
3596 assert(
MI.getOpcode() == TargetOpcode::G_OR);
3614 (LHSBits.
One | RHSBits.
Zero).isAllOnes()) {
3621 (LHSBits.
Zero | RHSBits.
One).isAllOnes()) {
3632 unsigned ExtBits =
MI.getOperand(2).getImm();
3633 unsigned TypeSize =
MRI.getType(Src).getScalarSizeInBits();
3634 return VT->computeNumSignBits(Src) >= (
TypeSize - ExtBits + 1);
3638 int64_t Cst,
bool IsVector,
bool IsFP) {
3640 return (ScalarSizeBits == 1 && Cst == -1) ||
3662 unsigned BuildUseCount = BV.getNumSources();
3663 if (BuildUseCount % 2 != 0)
3666 unsigned NumUnmerge = BuildUseCount / 2;
3672 if (!Unmerge || Unmerge->getNumDefs() != NumUnmerge)
3675 UnmergeSrc = Unmerge->getSourceReg();
3677 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
3678 LLT UnmergeSrcTy =
MRI.getType(UnmergeSrc);
3685 !
isLegal({TargetOpcode::G_CONCAT_VECTORS, {DstTy, UnmergeSrcTy}}))
3690 for (
unsigned I = 0;
I < NumUnmerge; ++
I) {
3691 auto MaybeUnmergeReg = BV.getSourceReg(
I);
3694 if (!LoopUnmerge || LoopUnmerge != Unmerge)
3697 if (LoopUnmerge->getOperand(
I).getReg() != MaybeUnmergeReg)
3702 if (Unmerge->getNumDefs() != NumUnmerge)
3706 for (
unsigned I = NumUnmerge;
I < BuildUseCount; ++
I) {
3709 if (
Undef->getOpcode() != TargetOpcode::G_IMPLICIT_DEF)
3720 assert(UnmergeSrc &&
"Expected there to be one matching G_UNMERGE_VALUES");
3721 B.setInstrAndDebugLoc(
MI);
3723 Register UndefVec =
B.buildUndef(
MRI.getType(UnmergeSrc)).getReg(0);
3724 B.buildConcatVectors(
MI.getOperand(0), {UnmergeSrc, UndefVec});
3726 MI.eraseFromParent();
3748 unsigned NumOperands =
BuildMI->getNumSources();
3758 for (
I = 0;
I < NumOperands; ++
I) {
3770 UnmergeMI != UnmergeSrcMI)
3781 for (;
I < NumOperands; ++
I) {
3788 LLT UnmergeSrcTy =
MRI.getType(MatchInfo);
3795 LLT UnmergeDstEltTy =
MRI.getType(UnmergeDstReg);
3796 if (UnmergeSrcEltTy != UnmergeDstEltTy)
3804 !
isLegal({TargetOpcode::G_CONCAT_VECTORS, {MidTy, UnmergeSrcTy}}))
3807 if (!
isLegal({TargetOpcode::G_TRUNC, {DstTy, MidTy}}))
3819 LLT DstTy =
MRI.getType(DstReg);
3820 LLT UnmergeSrcTy =
MRI.getType(MatchInfo);
3825 if (DstTyNumElt / UnmergeSrcTyNumElt == 1) {
3830 for (
unsigned I = 1;
I < DstTyNumElt / UnmergeSrcTyNumElt; ++
I)
3834 MidReg =
Builder.buildConcatVectors(MidTy, ConcatRegs).getReg(0);
3837 Builder.buildTrunc(DstReg, MidReg);
3838 MI.eraseFromParent();
3843 assert(
MI.getOpcode() == TargetOpcode::G_XOR);
3844 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
3845 const auto &TLI = *
Builder.getMF().getSubtarget().getTargetLowering();
3853 if (!
MRI.hasOneNonDBGUse(XorSrc))
3863 for (
unsigned I = 0;
I < RegsToNegate.
size(); ++
I) {
3865 if (!
MRI.hasOneNonDBGUse(Reg))
3870 switch (Def->getOpcode()) {
3875 case TargetOpcode::G_ICMP:
3881 case TargetOpcode::G_FCMP:
3887 case TargetOpcode::G_AND:
3888 case TargetOpcode::G_OR:
3894 RegsToNegate.
push_back(Def->getOperand(1).getReg());
3895 RegsToNegate.
push_back(Def->getOperand(2).getReg());
3903 if (Ty.isVector()) {
3907 if (!
isConstValidTrue(TLI, Ty.getScalarSizeInBits(), SplatCst,
true, IsFP))
3921 for (
Register Reg : RegsToNegate) {
3926 switch (Def->getOpcode()) {
3929 case TargetOpcode::G_ICMP:
3930 case TargetOpcode::G_FCMP: {
3937 case TargetOpcode::G_AND:
3938 Def->setDesc(
Builder.getTII().get(TargetOpcode::G_OR));
3940 case TargetOpcode::G_OR:
3941 Def->setDesc(
Builder.getTII().get(TargetOpcode::G_AND));
3948 MI.eraseFromParent();
3952 MachineInstr &
MI, std::pair<Register, Register> &MatchInfo)
const {
3954 assert(
MI.getOpcode() == TargetOpcode::G_XOR);
3958 Register SharedReg =
MI.getOperand(2).getReg();
3972 if (!
MRI.hasOneNonDBGUse(AndReg))
3979 return Y == SharedReg;
3983 MachineInstr &
MI, std::pair<Register, Register> &MatchInfo)
const {
3986 std::tie(
X,
Y) = MatchInfo;
3989 MI.setDesc(
Builder.getTII().get(TargetOpcode::G_AND));
3990 MI.getOperand(1).setReg(Not->getOperand(0).getReg());
3991 MI.getOperand(2).setReg(
Y);
3997 Register DstReg = PtrAdd.getReg(0);
3998 LLT Ty =
MRI.getType(DstReg);
4001 if (
DL.isNonIntegralAddressSpace(Ty.getScalarType().getAddressSpace()))
4004 if (Ty.isPointer()) {
4006 return ConstVal && *ConstVal == 0;
4009 assert(Ty.isVector() &&
"Expecting a vector type");
4018 Builder.buildIntToPtr(PtrAdd.getReg(0), PtrAdd.getOffsetReg());
4019 PtrAdd.eraseFromParent();
4026 Register Pow2Src1 =
MI.getOperand(2).getReg();
4027 LLT Ty =
MRI.getType(DstReg);
4030 auto NegOne =
Builder.buildConstant(Ty, -1);
4031 auto Add =
Builder.buildAdd(Ty, Pow2Src1, NegOne);
4033 MI.eraseFromParent();
4037 unsigned &SelectOpNo)
const {
4049 !
MRI.hasOneNonDBGUse(LHS)) {
4050 OtherOperandReg = LHS;
4054 !
MRI.hasOneNonDBGUse(RHS))
4072 unsigned BinOpcode =
MI.getOpcode();
4077 bool CanFoldNonConst =
4078 (BinOpcode == TargetOpcode::G_AND || BinOpcode == TargetOpcode::G_OR) &&
4083 if (CanFoldNonConst)
4108 LLT Ty =
MRI.getType(Dst);
4109 unsigned BinOpcode =
MI.getOpcode();
4116 if (SelectOperand == 1) {
4120 FoldTrue =
Builder.buildInstr(BinOpcode, {Ty}, {SelectTrue, RHS}).
getReg(0);
4122 Builder.buildInstr(BinOpcode, {Ty}, {SelectFalse, RHS}).
getReg(0);
4124 FoldTrue =
Builder.buildInstr(BinOpcode, {Ty}, {LHS, SelectTrue}).
getReg(0);
4126 Builder.buildInstr(BinOpcode, {Ty}, {LHS, SelectFalse}).
getReg(0);
4129 Builder.buildSelect(Dst, SelectCond, FoldTrue, FoldFalse,
MI.getFlags());
4130 MI.eraseFromParent();
4133std::optional<SmallVector<Register, 8>>
4134CombinerHelper::findCandidatesForLoadOrCombine(
const MachineInstr *Root)
const {
4135 assert(Root->
getOpcode() == TargetOpcode::G_OR &&
"Expected G_OR only!");
4164 const unsigned MaxIter =
4166 for (
unsigned Iter = 0; Iter < MaxIter; ++Iter) {
4175 return std::nullopt;
4191 if (RegsToVisit.
empty() || RegsToVisit.
size() % 2 != 0)
4192 return std::nullopt;
4204static std::optional<std::pair<GZExtLoad *, int64_t>>
4208 "Expected Reg to only have one non-debug use?");
4217 if (Shift % MemSizeInBits != 0)
4218 return std::nullopt;
4223 return std::nullopt;
4225 if (!
Load->isUnordered() ||
Load->getMemSizeInBits() != MemSizeInBits)
4226 return std::nullopt;
4228 return std::make_pair(
Load, Shift / MemSizeInBits);
4231std::optional<std::tuple<GZExtLoad *, int64_t, GZExtLoad *>>
4232CombinerHelper::findLoadOffsetsForLoadOrCombine(
4235 const unsigned MemSizeInBits)
const {
4238 SmallSetVector<const MachineInstr *, 8> Loads;
4244 GZExtLoad *LowestIdxLoad =
nullptr;
4247 SmallSet<int64_t, 8> SeenIdx;
4251 MachineBasicBlock *
MBB =
nullptr;
4252 const MachineMemOperand *MMO =
nullptr;
4255 GZExtLoad *EarliestLoad =
nullptr;
4258 GZExtLoad *LatestLoad =
nullptr;
4267 for (
auto Reg : RegsToVisit) {
4272 return std::nullopt;
4275 std::tie(
Load, DstPos) = *LoadAndPos;
4279 MachineBasicBlock *LoadMBB =
Load->getParent();
4283 return std::nullopt;
4286 auto &LoadMMO =
Load->getMMO();
4290 return std::nullopt;
4297 LoadPtr =
Load->getOperand(1).getReg();
4302 if (!SeenIdx.
insert(Idx).second)
4303 return std::nullopt;
4310 if (BasePtr != LoadPtr)
4311 return std::nullopt;
4313 if (Idx < LowestIdx) {
4315 LowestIdxLoad =
Load;
4322 if (!MemOffset2Idx.
try_emplace(DstPos, Idx).second)
4323 return std::nullopt;
4332 EarliestLoad =
Load;
4340 "Expected to find a load for each register?");
4341 assert(EarliestLoad != LatestLoad && EarliestLoad &&
4342 LatestLoad &&
"Expected at least two loads?");
4351 const unsigned MaxIter = 20;
4357 if (
MI.isLoadFoldBarrier())
4358 return std::nullopt;
4359 if (Iter++ == MaxIter)
4360 return std::nullopt;
4363 return std::make_tuple(LowestIdxLoad, LowestIdx, LatestLoad);
4369 assert(
MI.getOpcode() == TargetOpcode::G_OR);
4382 LLT Ty =
MRI.getType(Dst);
4388 const unsigned WideMemSizeInBits = Ty.getSizeInBits();
4389 if (WideMemSizeInBits < 16 || WideMemSizeInBits % 8 != 0)
4393 auto RegsToVisit = findCandidatesForLoadOrCombine(&
MI);
4400 const unsigned NarrowMemSizeInBits = WideMemSizeInBits / RegsToVisit->size();
4401 if (NarrowMemSizeInBits % 8 != 0)
4414 auto MaybeLoadInfo = findLoadOffsetsForLoadOrCombine(
4415 MemOffset2Idx, *RegsToVisit, NarrowMemSizeInBits);
4418 std::tie(LowestIdxLoad, LowestIdx, LatestLoad) = *MaybeLoadInfo;
4425 std::optional<bool> IsBigEndian =
isBigEndian(MemOffset2Idx, LowestIdx);
4428 bool NeedsBSwap = IsBigEndianTarget != *IsBigEndian;
4440 const unsigned NumLoadsInTy = WideMemSizeInBits / NarrowMemSizeInBits;
4441 const unsigned ZeroByteOffset =
4445 auto ZeroOffsetIdx = MemOffset2Idx.
find(ZeroByteOffset);
4446 if (ZeroOffsetIdx == MemOffset2Idx.
end() ||
4447 ZeroOffsetIdx->second != LowestIdx)
4457 {TargetOpcode::G_LOAD, {Ty,
MRI.getType(Ptr)}, {MMDesc}}))
4471 MIB.setInstrAndDebugLoc(*LatestLoad);
4472 Register LoadDst = NeedsBSwap ?
MRI.cloneVirtualRegister(Dst) : Dst;
4473 MIB.buildLoad(LoadDst, Ptr, *NewMMO);
4475 MIB.buildBSwap(Dst, LoadDst);
4487 if (
MRI.getType(DstReg).isVector())
4491 if (!
MRI.hasOneNonDBGUse(DstReg))
4493 ExtMI = &*
MRI.use_instr_nodbg_begin(DstReg);
4495 case TargetOpcode::G_ANYEXT:
4497 case TargetOpcode::G_ZEXT:
4498 case TargetOpcode::G_SEXT:
4505 if (
Builder.getTII().isExtendLikelyToBeFolded(*ExtMI,
MRI))
4512 for (
unsigned I = 0;
I <
PHI.getNumIncomingValues(); ++
I) {
4514 switch (
DefMI->getOpcode()) {
4515 case TargetOpcode::G_LOAD:
4516 case TargetOpcode::G_TRUNC:
4517 case TargetOpcode::G_SEXT:
4518 case TargetOpcode::G_ZEXT:
4519 case TargetOpcode::G_ANYEXT:
4520 case TargetOpcode::G_CONSTANT:
4524 if (InSrcs.
size() > 2)
4538 LLT ExtTy =
MRI.getType(DstReg);
4545 for (
unsigned I = 0;
I <
PHI.getNumIncomingValues(); ++
I) {
4546 auto SrcReg =
PHI.getIncomingValue(
I);
4550 if (!SrcMIs.
insert(SrcMI))
4556 if (InsertPt !=
MBB->end() && InsertPt->isPHI())
4557 InsertPt =
MBB->getFirstNonPHI();
4562 OldToNewSrcMap[SrcMI] = NewExt;
4567 auto NewPhi =
Builder.buildInstrNoInsert(TargetOpcode::G_PHI);
4568 NewPhi.addDef(DstReg);
4571 NewPhi.addMBB(MO.getMBB());
4574 auto *NewSrc = OldToNewSrcMap[
MRI.getVRegDef(MO.getReg())];
4575 NewPhi.addUse(NewSrc->getOperand(0).getReg());
4583 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT);
4587 LLT SrcTy =
MRI.getType(SrcVec);
4588 if (SrcTy.isScalableVector())
4592 if (!Cst || Cst->Value.getZExtValue() >= SrcTy.getNumElements())
4595 unsigned VecIdx = Cst->Value.getZExtValue();
4607 if (SrcVecMI->
getOpcode() != TargetOpcode::G_BUILD_VECTOR &&
4608 SrcVecMI->
getOpcode() != TargetOpcode::G_BUILD_VECTOR_TRUNC)
4612 if (!
MRI.hasOneNonDBGUse(SrcVec) &&
4624 LLT ScalarTy =
MRI.getType(Reg);
4626 LLT DstTy =
MRI.getType(DstReg);
4628 if (ScalarTy != DstTy) {
4630 Builder.buildTrunc(DstReg, Reg);
4631 MI.eraseFromParent();
4639 SmallVectorImpl<std::pair<Register, MachineInstr *>> &SrcDstPairs)
const {
4640 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
4658 LLT DstTy =
MRI.getType(DstReg);
4663 if (
II.getOpcode() != TargetOpcode::G_EXTRACT_VECTOR_ELT)
4668 unsigned Idx = Cst->getZExtValue();
4671 ExtractedElts.
set(Idx);
4672 SrcDstPairs.emplace_back(
4673 std::make_pair(
MI.getOperand(Idx + 1).getReg(), &
II));
4676 return ExtractedElts.
all();
4681 SmallVectorImpl<std::pair<Register, MachineInstr *>> &SrcDstPairs)
const {
4682 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
4683 for (
auto &Pair : SrcDstPairs) {
4684 auto *ExtMI = Pair.second;
4686 ExtMI->eraseFromParent();
4688 MI.eraseFromParent();
4695 MI.eraseFromParent();
4705 bool AllowScalarConstants,
4707 assert(
MI.getOpcode() == TargetOpcode::G_OR);
4710 LLT Ty =
MRI.getType(Dst);
4711 unsigned BitWidth = Ty.getScalarSizeInBits();
4713 Register ShlSrc, ShlAmt, LShrSrc, LShrAmt, Amt;
4714 unsigned FshOpc = 0;
4725 int64_t CstShlAmt = 0, CstLShrAmt;
4728 CstShlAmt + CstLShrAmt ==
BitWidth) {
4729 FshOpc = TargetOpcode::G_FSHR;
4735 FshOpc = TargetOpcode::G_FSHL;
4740 FshOpc = TargetOpcode::G_FSHR;
4745 LLT AmtTy =
MRI.getType(Amt);
4747 (!AllowScalarConstants || CstShlAmt == 0 || !Ty.isScalar()))
4751 B.buildInstr(FshOpc, {Dst}, {ShlSrc, LShrSrc, Amt});
4758 unsigned Opc =
MI.getOpcode();
4759 assert(
Opc == TargetOpcode::G_FSHL ||
Opc == TargetOpcode::G_FSHR);
4764 unsigned RotateOpc =
4765 Opc == TargetOpcode::G_FSHL ? TargetOpcode::G_ROTL : TargetOpcode::G_ROTR;
4770 unsigned Opc =
MI.getOpcode();
4771 assert(
Opc == TargetOpcode::G_FSHL ||
Opc == TargetOpcode::G_FSHR);
4772 bool IsFSHL =
Opc == TargetOpcode::G_FSHL;
4774 MI.setDesc(
Builder.getTII().get(IsFSHL ? TargetOpcode::G_ROTL
4775 : TargetOpcode::G_ROTR));
4776 MI.removeOperand(2);
4782 assert(
MI.getOpcode() == TargetOpcode::G_ROTL ||
4783 MI.getOpcode() == TargetOpcode::G_ROTR);
4785 MRI.getType(
MI.getOperand(0).getReg()).getScalarSizeInBits();
4787 bool OutOfRange =
false;
4788 auto MatchOutOfRange = [Bitsize, &OutOfRange](
const Constant *
C) {
4790 OutOfRange |= CI->getValue().uge(Bitsize);
4797 assert(
MI.getOpcode() == TargetOpcode::G_ROTL ||
4798 MI.getOpcode() == TargetOpcode::G_ROTR);
4800 MRI.getType(
MI.getOperand(0).getReg()).getScalarSizeInBits();
4802 LLT AmtTy =
MRI.getType(Amt);
4803 auto Bits =
Builder.buildConstant(AmtTy, Bitsize);
4804 Amt =
Builder.buildURem(AmtTy,
MI.getOperand(2).getReg(), Bits).getReg(0);
4806 MI.getOperand(2).setReg(Amt);
4811 int64_t &MatchInfo)
const {
4812 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
4823 auto KnownRHS =
VT->getKnownBits(
MI.getOperand(3).getReg());
4824 if (KnownRHS.isUnknown())
4827 std::optional<bool> KnownVal;
4828 if (KnownRHS.isZero()) {
4838 auto KnownLHS =
VT->getKnownBits(
MI.getOperand(2).getReg());
4848 MRI.getType(
MI.getOperand(0).getReg()).isVector(),
4857 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
4873 LLT DstTy =
MRI.getType(Dst);
4881 auto KnownLHS =
VT->getKnownBits(LHS);
4882 if (KnownLHS.getMinValue() != 0 || KnownLHS.getMaxValue() != 1)
4885 LLT LHSTy =
MRI.getType(LHS);
4888 unsigned Op = TargetOpcode::COPY;
4889 if (DstSize != LHSSize)
4890 Op = DstSize < LHSSize ? TargetOpcode::G_TRUNC : TargetOpcode::G_ZEXT;
4901 assert(
MI.getOpcode() == TargetOpcode::G_AND);
4905 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
4911 int64_t AndMaskBits;
4919 if (AndMaskBits & OrMaskBits)
4925 if (
MI.getOperand(1).getReg() == AndMaskReg)
4926 MI.getOperand(2).setReg(AndMaskReg);
4927 MI.getOperand(1).setReg(Src);
4937 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
4940 LLT Ty =
MRI.getType(Src);
4942 if (!
LI || !
LI->isLegalOrCustom({TargetOpcode::G_SBFX, {Ty, ExtractTy}}))
4944 int64_t Width =
MI.getOperand(2).getImm();
4952 if (ShiftImm < 0 || ShiftImm + Width > Ty.getScalarSizeInBits())
4956 auto Cst1 =
B.buildConstant(ExtractTy, ShiftImm);
4957 auto Cst2 =
B.buildConstant(ExtractTy, Width);
4958 B.buildSbfx(Dst, ShiftSrc, Cst1, Cst2);
4968 LLT Ty =
MRI.getType(Dst);
4972 if (
LI && !
LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
4975 int64_t AndImm, LSBImm;
4977 const unsigned Size = Ty.getScalarSizeInBits();
4984 auto MaybeMask =
static_cast<uint64_t
>(AndImm);
4985 if (MaybeMask & (MaybeMask + 1))
4989 if (
static_cast<uint64_t
>(LSBImm) >=
Size)
4994 auto WidthCst =
B.buildConstant(ExtractTy, Width);
4995 auto LSBCst =
B.buildConstant(ExtractTy, LSBImm);
4996 B.buildInstr(TargetOpcode::G_UBFX, {Dst}, {ShiftSrc, LSBCst, WidthCst});
5004 const unsigned Opcode =
MI.getOpcode();
5005 assert(Opcode == TargetOpcode::G_ASHR || Opcode == TargetOpcode::G_LSHR);
5007 const Register Dst =
MI.getOperand(0).getReg();
5009 const unsigned ExtrOpcode = Opcode == TargetOpcode::G_ASHR
5010 ? TargetOpcode::G_SBFX
5011 : TargetOpcode::G_UBFX;
5014 LLT Ty =
MRI.getType(Dst);
5016 if (!
LI || !
LI->isLegalOrCustom({ExtrOpcode, {Ty, ExtractTy}}))
5022 const unsigned Size = Ty.getScalarSizeInBits();
5032 if (ShlAmt < 0 || ShlAmt > ShrAmt || ShrAmt >=
Size)
5036 if (Opcode == TargetOpcode::G_ASHR && ShlAmt == ShrAmt)
5040 const int64_t Pos = ShrAmt - ShlAmt;
5041 const int64_t Width =
Size - ShrAmt;
5044 auto WidthCst =
B.buildConstant(ExtractTy, Width);
5045 auto PosCst =
B.buildConstant(ExtractTy, Pos);
5046 B.buildInstr(ExtrOpcode, {Dst}, {ShlSrc, PosCst, WidthCst});
5054 const unsigned Opcode =
MI.getOpcode();
5055 assert(Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_ASHR);
5057 const Register Dst =
MI.getOperand(0).getReg();
5058 LLT Ty =
MRI.getType(Dst);
5060 if (
LI && !
LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
5073 const unsigned Size = Ty.getScalarSizeInBits();
5074 if (ShrAmt < 0 || ShrAmt >=
Size)
5078 if (0 == (SMask >> ShrAmt)) {
5080 B.buildConstant(Dst, 0);
5093 const int64_t Pos = ShrAmt;
5098 if (Opcode == TargetOpcode::G_ASHR && Width + ShrAmt ==
Size)
5102 auto WidthCst =
B.buildConstant(ExtractTy, Width);
5103 auto PosCst =
B.buildConstant(ExtractTy, Pos);
5104 B.buildInstr(TargetOpcode::G_UBFX, {Dst}, {AndSrc, PosCst, WidthCst});
5109bool CombinerHelper::reassociationCanBreakAddressingModePattern(
5113 Register Src1Reg = PtrAdd.getBaseReg();
5118 Register Src2Reg = PtrAdd.getOffsetReg();
5120 if (
MRI.hasOneNonDBGUse(Src1Reg))
5130 const APInt &C1APIntVal = *C1;
5131 const APInt &C2APIntVal = *C2;
5132 const int64_t CombinedValue = (C1APIntVal + C2APIntVal).getSExtValue();
5134 for (
auto &
UseMI :
MRI.use_nodbg_instructions(PtrAdd.getReg(0))) {
5137 MachineInstr *ConvUseMI = &
UseMI;
5138 unsigned ConvUseOpc = ConvUseMI->
getOpcode();
5139 while (ConvUseOpc == TargetOpcode::G_INTTOPTR ||
5140 ConvUseOpc == TargetOpcode::G_PTRTOINT) {
5142 if (!
MRI.hasOneNonDBGUse(DefReg))
5144 ConvUseMI = &*
MRI.use_instr_nodbg_begin(DefReg);
5153 TargetLoweringBase::AddrMode AM;
5156 unsigned AS =
MRI.getType(LdStMI->getPointerReg()).getAddressSpace();
5158 PtrAdd.getMF()->getFunction().getContext());
5159 const auto &TLI = *PtrAdd.getMF()->getSubtarget().getTargetLowering();
5160 if (!TLI.isLegalAddressingMode(PtrAdd.getMF()->getDataLayout(), AM,
5166 if (!TLI.isLegalAddressingMode(PtrAdd.getMF()->getDataLayout(), AM,
5178 Register Src1Reg =
MI.getOperand(1).getReg();
5179 if (RHS->getOpcode() != TargetOpcode::G_ADD)
5191 unsigned PtrAddFlags =
MI.getFlags();
5192 unsigned AddFlags = RHS->getFlags();
5205 LLT PtrTy =
MRI.getType(
MI.getOperand(0).getReg());
5208 Builder.buildPtrAdd(PtrTy, Src1Reg, RHS->getOperand(1).getReg(), Flags);
5210 MI.getOperand(1).setReg(NewBase.getReg(0));
5211 MI.getOperand(2).setReg(RHS->getOperand(2).getReg());
5215 return !reassociationCanBreakAddressingModePattern(
MI);
5225 std::optional<ValueAndVReg> LHSCstOff;
5235 unsigned PtrAddFlags =
MI.getFlags();
5236 unsigned LHSPtrAddFlags = LHSPtrAdd->getFlags();
5238 bool IsNoUSWrap = IsNoUWrap && (PtrAddFlags & LHSPtrAddFlags &
5240 bool IsInBounds = IsNoUWrap && (PtrAddFlags & LHSPtrAddFlags &
5254 LHSPtrAdd->moveBefore(&
MI);
5257 auto NewCst =
B.buildConstant(
MRI.getType(RHSReg), LHSCstOff->Value);
5259 MI.getOperand(2).setReg(NewCst.getReg(0));
5262 Observer.changingInstr(*LHSPtrAdd);
5263 LHSPtrAdd->getOperand(2).setReg(RHSReg);
5264 LHSPtrAdd->setFlags(Flags);
5267 return !reassociationCanBreakAddressingModePattern(
MI);
5278 Register Src2Reg =
MI.getOperand(2).getReg();
5279 Register LHSSrc1 = LHSPtrAdd->getBaseReg();
5280 Register LHSSrc2 = LHSPtrAdd->getOffsetReg();
5293 unsigned PtrAddFlags =
MI.getFlags();
5294 unsigned LHSPtrAddFlags = LHSPtrAdd->getFlags();
5307 auto NewCst =
B.buildConstant(
MRI.getType(Src2Reg), *C1 + *C2);
5309 MI.getOperand(1).setReg(LHSSrc1);
5310 MI.getOperand(2).setReg(NewCst.getReg(0));
5314 return !reassociationCanBreakAddressingModePattern(
MI);
5354 LLT OpRHSTy =
MRI.getType(OpRHS);
5371 auto NewCst =
B.buildInstr(
Opc, {OpRHSTy}, {OpLHSRHS, OpRHS});
5372 B.buildInstr(
Opc, {DstReg}, {OpLHSLHS, NewCst});
5380 auto NewLHSLHS =
B.buildInstr(
Opc, {OpRHSTy}, {OpLHSLHS, OpRHS});
5381 B.buildInstr(
Opc, {DstReg}, {NewLHSLHS, OpLHSRHS});
5394 unsigned Opc =
MI.getOpcode();
5407 APInt &MatchInfo)
const {
5408 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
5412 MatchInfo = *MaybeCst;
5423 MI.getOperand(1).getReg(),
MRI);
5428 if (Csts.size() == 1)
5429 B.buildConstant(Dst, Csts[0]);
5431 B.buildBuildVectorConstant(Dst, Csts);
5437 APInt &MatchInfo)
const {
5443 MatchInfo = *MaybeCst;
5455 ConstantFP::get(
MI.getMF()->getFunction().getContext(), *MaybeCst);
5461 assert(
MI.getOpcode() == TargetOpcode::G_FMA ||
5462 MI.getOpcode() == TargetOpcode::G_FMAD);
5463 auto [
_, Op1, Op2, Op3] =
MI.getFirst4Regs();
5480 MatchInfo = ConstantFP::get(
MI.getMF()->getFunction().getContext(), Op1F);
5503 assert(
MI.getOpcode() == TargetOpcode::G_AND);
5507 LLT WideTy =
MRI.getType(Dst);
5511 if (!WideTy.
isScalar() || !
MRI.hasOneNonDBGUse(AndLHS))
5527 case TargetOpcode::G_ADD:
5528 case TargetOpcode::G_SUB:
5529 case TargetOpcode::G_MUL:
5530 case TargetOpcode::G_AND:
5531 case TargetOpcode::G_OR:
5532 case TargetOpcode::G_XOR:
5540 auto Mask = Cst->Value;
5545 unsigned NarrowWidth = Mask.countr_one();
5551 auto &MF = *
MI.getMF();
5554 if (!TLI.isTruncateFree(WideTy, NarrowTy, Ctx) ||
5555 !TLI.isZExtFree(NarrowTy, WideTy, Ctx))
5563 auto NarrowLHS =
Builder.buildTrunc(NarrowTy, BinOpLHS);
5564 auto NarrowRHS =
Builder.buildTrunc(NarrowTy, BinOpRHS);
5566 Builder.buildInstr(LHSOpc, {NarrowTy}, {NarrowLHS, NarrowRHS});
5567 auto Ext =
Builder.buildZExt(WideTy, NarrowBinOp);
5569 MI.getOperand(1).setReg(Ext.getReg(0));
5577 unsigned Opc =
MI.getOpcode();
5578 assert(
Opc == TargetOpcode::G_UMULO ||
Opc == TargetOpcode::G_SMULO);
5585 unsigned NewOpc =
Opc == TargetOpcode::G_UMULO ? TargetOpcode::G_UADDO
5586 : TargetOpcode::G_SADDO;
5587 MI.setDesc(
Builder.getTII().get(NewOpc));
5588 MI.getOperand(3).setReg(
MI.getOperand(2).getReg());
5597 assert(
MI.getOpcode() == TargetOpcode::G_UMULO ||
5598 MI.getOpcode() == TargetOpcode::G_SMULO);
5607 B.buildConstant(Dst, 0);
5608 B.buildConstant(Carry, 0);
5617 assert(
MI.getOpcode() == TargetOpcode::G_UADDE ||
5618 MI.getOpcode() == TargetOpcode::G_SADDE ||
5619 MI.getOpcode() == TargetOpcode::G_USUBE ||
5620 MI.getOpcode() == TargetOpcode::G_SSUBE);
5625 switch (
MI.getOpcode()) {
5626 case TargetOpcode::G_UADDE:
5627 NewOpcode = TargetOpcode::G_UADDO;
5629 case TargetOpcode::G_SADDE:
5630 NewOpcode = TargetOpcode::G_SADDO;
5632 case TargetOpcode::G_USUBE:
5633 NewOpcode = TargetOpcode::G_USUBO;
5635 case TargetOpcode::G_SSUBE:
5636 NewOpcode = TargetOpcode::G_SSUBO;
5640 MI.setDesc(
B.getTII().get(NewOpcode));
5641 MI.removeOperand(4);
5649 assert(
MI.getOpcode() == TargetOpcode::G_SUB);
5682 auto Zero =
B.buildConstant(
MRI.getType(Dst), 0);
5683 B.buildSub(Dst, Zero, ReplaceReg);
5692 unsigned Opcode =
MI.getOpcode();
5693 assert(Opcode == TargetOpcode::G_UDIV || Opcode == TargetOpcode::G_UREM);
5695 Register Dst = UDivorRem.getReg(0);
5696 Register LHS = UDivorRem.getReg(1);
5697 Register RHS = UDivorRem.getReg(2);
5698 LLT Ty =
MRI.getType(Dst);
5706 bool UseSRL =
false;
5711 auto BuildExactUDIVPattern = [&](
const Constant *
C) {
5713 if (IsSplat && !Factors.
empty()) {
5720 APInt Divisor = CI->getValue();
5729 Shifts.
push_back(MIB.buildConstant(ScalarShiftAmtTy, Shift).getReg(0));
5730 Factors.
push_back(MIB.buildConstant(ScalarTy, Factor).getReg(0));
5740 if (Ty.isVector()) {
5741 Shift = MIB.buildBuildVector(ShiftAmtTy, Shifts).getReg(0);
5742 Factor = MIB.buildBuildVector(Ty, Factors).getReg(0);
5745 Factor = Factors[0];
5753 return MIB.buildMul(Ty, Res, Factor);
5756 unsigned KnownLeadingZeros =
5757 VT ?
VT->getKnownBits(LHS).countMinLeadingZeros() : 0;
5759 bool UseNPQ =
false;
5761 auto BuildUDIVPattern = [&](
const Constant *
C) {
5763 const APInt &Divisor = CI->getValue();
5765 bool SelNPQ =
false;
5767 unsigned PreShift = 0, PostShift = 0;
5772 if (!Divisor.
isOne()) {
5778 Divisor, std::min(KnownLeadingZeros, Divisor.
countl_zero()));
5780 Magic = std::move(magics.
Magic);
5783 "We shouldn't generate an undefined shift!");
5785 "We shouldn't generate an undefined shift!");
5789 SelNPQ = magics.
IsAdd;
5793 MIB.buildConstant(ScalarShiftAmtTy, PreShift).getReg(0));
5794 MagicFactors.
push_back(MIB.buildConstant(ScalarTy, Magic).getReg(0));
5796 MIB.buildConstant(ScalarTy,
5801 MIB.buildConstant(ScalarShiftAmtTy, PostShift).getReg(0));
5809 assert(Matched &&
"Expected unary predicate match to succeed");
5811 Register PreShift, PostShift, MagicFactor, NPQFactor;
5814 PreShift = MIB.buildBuildVector(ShiftAmtTy, PreShifts).getReg(0);
5815 MagicFactor = MIB.buildBuildVector(Ty, MagicFactors).getReg(0);
5816 NPQFactor = MIB.buildBuildVector(Ty, NPQFactors).getReg(0);
5817 PostShift = MIB.buildBuildVector(ShiftAmtTy, PostShifts).getReg(0);
5820 "Non-build_vector operation should have been a scalar");
5821 PreShift = PreShifts[0];
5822 MagicFactor = MagicFactors[0];
5823 PostShift = PostShifts[0];
5827 Q = MIB.buildLShr(Ty, Q, PreShift).getReg(0);
5830 Q = MIB.buildUMulH(Ty, Q, MagicFactor).getReg(0);
5833 Register NPQ = MIB.buildSub(Ty, LHS, Q).getReg(0);
5838 NPQ = MIB.buildUMulH(Ty, NPQ, NPQFactor).getReg(0);
5840 NPQ = MIB.buildLShr(Ty, NPQ, MIB.buildConstant(ShiftAmtTy, 1)).getReg(0);
5842 Q = MIB.buildAdd(Ty, NPQ, Q).getReg(0);
5845 Q = MIB.buildLShr(Ty, Q, PostShift).getReg(0);
5846 auto One = MIB.buildConstant(Ty, 1);
5847 auto IsOne = MIB.buildICmp(
5851 auto ret = MIB.buildSelect(Ty, IsOne, LHS, Q);
5853 if (Opcode == TargetOpcode::G_UREM) {
5854 auto Prod = MIB.buildMul(Ty, ret, RHS);
5855 return MIB.buildSub(Ty, LHS, Prod);
5861 unsigned Opcode =
MI.getOpcode();
5862 assert(Opcode == TargetOpcode::G_UDIV || Opcode == TargetOpcode::G_UREM);
5865 LLT DstTy =
MRI.getType(Dst);
5867 auto &MF = *
MI.getMF();
5868 AttributeList Attr = MF.getFunction().getAttributes();
5877 if (MF.getFunction().hasMinSize())
5880 if (Opcode == TargetOpcode::G_UDIV &&
5883 MRI, RHS, [](
const Constant *
C) {
return C && !
C->isNullValue(); });
5898 {TargetOpcode::G_ICMP,
5902 if (Opcode == TargetOpcode::G_UREM &&
5908 MRI, RHS, [](
const Constant *
C) {
return C && !
C->isNullValue(); });
5917 unsigned Opcode =
MI.getOpcode();
5918 assert(Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_SREM);
5921 LLT DstTy =
MRI.getType(Dst);
5925 auto &MF = *
MI.getMF();
5926 AttributeList Attr = MF.getFunction().getAttributes();
5935 if (MF.getFunction().hasMinSize())
5939 if (Opcode == TargetOpcode::G_SDIV &&
5942 MRI, RHS, [](
const Constant *
C) {
return C && !
C->isNullValue(); });
5954 if (!
isLegal({TargetOpcode::G_SMULH, {DstTy}}) &&
5957 if (Opcode == TargetOpcode::G_SREM &&
5963 MRI, RHS, [](
const Constant *
C) {
return C && !
C->isNullValue(); });
5972 unsigned Opcode =
MI.getOpcode();
5973 assert(
MI.getOpcode() == TargetOpcode::G_SDIV ||
5974 Opcode == TargetOpcode::G_SREM);
5976 Register Dst = SDivorRem.getReg(0);
5977 Register LHS = SDivorRem.getReg(1);
5978 Register RHS = SDivorRem.getReg(2);
5979 LLT Ty =
MRI.getType(Dst);
5986 bool UseSRA =
false;
5992 auto BuildExactSDIVPattern = [&](
const Constant *
C) {
5994 if (IsSplat && !ExactFactors.
empty()) {
5996 ExactFactors.
push_back(ExactFactors[0]);
6001 APInt Divisor = CI->getValue();
6011 ExactShifts.
push_back(MIB.buildConstant(ScalarShiftAmtTy, Shift).getReg(0));
6012 ExactFactors.
push_back(MIB.buildConstant(ScalarTy, Factor).getReg(0));
6020 assert(Matched &&
"Expected unary predicate match to succeed");
6023 if (Ty.isVector()) {
6024 Shift = MIB.buildBuildVector(ShiftAmtTy, ExactShifts).getReg(0);
6025 Factor = MIB.buildBuildVector(Ty, ExactFactors).getReg(0);
6027 Shift = ExactShifts[0];
6028 Factor = ExactFactors[0];
6036 return MIB.buildMul(Ty, Res, Factor);
6041 auto BuildSDIVPattern = [&](
const Constant *
C) {
6043 const APInt &Divisor = CI->getValue();
6047 int NumeratorFactor = 0;
6058 NumeratorFactor = 1;
6061 NumeratorFactor = -1;
6064 MagicFactors.
push_back(MIB.buildConstant(ScalarTy, Magics.
Magic).getReg(0));
6065 Factors.
push_back(MIB.buildConstant(ScalarTy, NumeratorFactor).getReg(0));
6067 MIB.buildConstant(ScalarShiftAmtTy, Magics.
ShiftAmount).getReg(0));
6068 ShiftMasks.
push_back(MIB.buildConstant(ScalarTy, ShiftMask).getReg(0));
6076 assert(Matched &&
"Expected unary predicate match to succeed");
6078 Register MagicFactor, Factor, Shift, ShiftMask;
6081 MagicFactor = MIB.buildBuildVector(Ty, MagicFactors).getReg(0);
6082 Factor = MIB.buildBuildVector(Ty, Factors).getReg(0);
6083 Shift = MIB.buildBuildVector(ShiftAmtTy, Shifts).getReg(0);
6084 ShiftMask = MIB.buildBuildVector(Ty, ShiftMasks).getReg(0);
6087 "Non-build_vector operation should have been a scalar");
6088 MagicFactor = MagicFactors[0];
6089 Factor = Factors[0];
6091 ShiftMask = ShiftMasks[0];
6095 Q = MIB.buildSMulH(Ty, LHS, MagicFactor).getReg(0);
6098 Factor = MIB.buildMul(Ty, LHS, Factor).getReg(0);
6099 Q = MIB.buildAdd(Ty, Q, Factor).getReg(0);
6102 Q = MIB.buildAShr(Ty, Q, Shift).getReg(0);
6105 auto SignShift = MIB.buildConstant(ShiftAmtTy, EltBits - 1);
6106 auto T = MIB.buildLShr(Ty, Q, SignShift);
6107 T = MIB.buildAnd(Ty,
T, ShiftMask);
6108 auto ret = MIB.buildAdd(Ty, Q,
T);
6110 if (Opcode == TargetOpcode::G_SREM) {
6111 auto Prod = MIB.buildMul(Ty, ret, RHS);
6112 return MIB.buildSub(Ty, LHS, Prod);
6118 assert((
MI.getOpcode() == TargetOpcode::G_SDIV ||
6119 MI.getOpcode() == TargetOpcode::G_UDIV) &&
6120 "Expected SDIV or UDIV");
6123 auto MatchPow2 = [&](
const Constant *
C) {
6125 return CI && (CI->getValue().isPowerOf2() ||
6126 (IsSigned && CI->getValue().isNegatedPowerOf2()));
6132 assert(
MI.getOpcode() == TargetOpcode::G_SDIV &&
"Expected SDIV");
6137 LLT Ty =
MRI.getType(Dst);
6157 unsigned BitWidth = Ty.getScalarSizeInBits();
6158 auto Zero =
Builder.buildConstant(Ty, 0);
6161 auto C1 =
Builder.buildCTTZ(ShiftAmtTy, RHS);
6162 auto Inexact =
Builder.buildSub(ShiftAmtTy, Bits, C1);
6164 auto Sign =
Builder.buildAShr(
6168 auto LSrl =
Builder.buildLShr(Ty, Sign, Inexact);
6174 auto One =
Builder.buildConstant(Ty, 1);
6175 auto MinusOne =
Builder.buildConstant(Ty, -1);
6179 auto IsOneOrMinusOne =
Builder.buildOr(CCVT, IsOne, IsMinusOne);
6180 AShr =
Builder.buildSelect(Ty, IsOneOrMinusOne, LHS, AShr);
6184 auto Neg =
Builder.buildNeg(Ty, AShr);
6186 Builder.buildSelect(
MI.getOperand(0).getReg(), IsNeg, Neg, AShr);
6187 MI.eraseFromParent();
6191 assert(
MI.getOpcode() == TargetOpcode::G_UDIV &&
"Expected UDIV");
6196 LLT Ty =
MRI.getType(Dst);
6199 auto C1 =
Builder.buildCTTZ(ShiftAmtTy, RHS);
6200 Builder.buildLShr(
MI.getOperand(0).getReg(), LHS, C1);
6201 MI.eraseFromParent();
6205 assert(
MI.getOpcode() == TargetOpcode::G_SREM &&
"Expected SREM");
6210 LLT Ty =
MRI.getType(Dst);
6229 unsigned BitWidth = Ty.getScalarSizeInBits();
6230 auto AbsRHS =
Builder.buildAbs(Ty, RHS);
6231 auto Mask =
Builder.buildSub(Ty, AbsRHS,
Builder.buildConstant(Ty, 1));
6233 auto Sign =
Builder.buildAShr(Ty, LHS, BWMinusOne);
6234 auto Bias =
Builder.buildAnd(Ty, Sign, Mask);
6235 auto Biased =
Builder.buildAdd(Ty, LHS, Bias);
6238 MI.eraseFromParent();
6242 assert(
MI.getOpcode() == TargetOpcode::G_UMULH);
6245 LLT Ty =
MRI.getType(Dst);
6246 LLT RHSTy =
MRI.getType(RHS);
6248 auto MatchPow2ExceptOne = [&](
const Constant *
C) {
6250 return CI->getValue().isPowerOf2() && !CI->getValue().isOne();
6265 LLT Ty =
MRI.getType(Dst);
6271 Builder.buildSub(Ty,
Builder.buildConstant(Ty, NumEltBits), LogBase2);
6272 auto Trunc =
Builder.buildZExtOrTrunc(ShiftAmtTy, ShiftAmt);
6273 Builder.buildLShr(Dst, LHS, Trunc);
6274 MI.eraseFromParent();
6281 LLT DstTy =
MRI.getType(Dst);
6282 LLT SrcTy =
MRI.getType(Src);
6284 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6285 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
6288 {TargetOpcode::G_TRUNC_SSAT_S, {DstTy, SrcTy}}))
6317 Builder.buildTruncSSatS(Dst, MatchInfo);
6318 MI.eraseFromParent();
6325 LLT DstTy =
MRI.getType(Dst);
6326 LLT SrcTy =
MRI.getType(Src);
6328 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6329 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
6332 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6350 Builder.buildTruncSSatU(Dst, MatchInfo);
6351 MI.eraseFromParent();
6358 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6359 LLT SrcTy =
MRI.getType(Val);
6361 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6362 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
6365 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6374 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6383 unsigned Opc =
MI.getOpcode();
6384 assert(
Opc == TargetOpcode::G_FADD ||
Opc == TargetOpcode::G_FSUB ||
6385 Opc == TargetOpcode::G_FMUL ||
Opc == TargetOpcode::G_FDIV ||
6386 Opc == TargetOpcode::G_FMAD ||
Opc == TargetOpcode::G_FMA);
6398 Opc = TargetOpcode::G_FSUB;
6403 Opc = TargetOpcode::G_FADD;
6409 else if ((
Opc == TargetOpcode::G_FMUL ||
Opc == TargetOpcode::G_FDIV ||
6410 Opc == TargetOpcode::G_FMAD ||
Opc == TargetOpcode::G_FMA) &&
6419 MI.setDesc(
B.getTII().get(
Opc));
6420 MI.getOperand(1).setReg(
X);
6421 MI.getOperand(2).setReg(
Y);
6429 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
6432 MatchInfo =
MI.getOperand(2).getReg();
6433 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
6435 const auto LHSCst = Ty.isVector()
6442 if (LHSCst->Value.isNegZero())
6446 if (LHSCst->Value.isPosZero())
6456 Dst,
Builder.buildFCanonicalize(
MRI.getType(Dst), MatchInfo).getReg(0));
6463 if (
MI.getOpcode() != TargetOpcode::G_FMUL)
6477 bool &AllowFusionGlobally,
6479 bool CanReassociate)
const {
6481 auto *MF =
MI.getMF();
6482 const auto &TLI = *MF->getSubtarget().getTargetLowering();
6484 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
6492 bool HasFMA = TLI.isFMAFasterThanFMulAndFAdd(*MF, DstType) &&
6495 if (!HasFMAD && !HasFMA)
6503 Aggressive = TLI.enableAggressiveFMAFusion(DstType);
6510 assert(
MI.getOpcode() == TargetOpcode::G_FADD);
6512 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6524 unsigned PreferredFusedOpcode =
6525 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6538 unsigned Flags =
MI.getFlags() & LHS.MI->getFlags();
6540 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6541 {LHS.MI->getOperand(1).getReg(),
6542 LHS.MI->getOperand(2).getReg(), RHS.Reg},
6551 unsigned Flags =
MI.getFlags() & RHS.MI->getFlags();
6553 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6554 {RHS.MI->getOperand(1).getReg(),
6555 RHS.MI->getOperand(2).getReg(), LHS.Reg},
6567 assert(
MI.getOpcode() == TargetOpcode::G_FADD);
6569 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6573 const auto &TLI = *
MI.getMF()->getSubtarget().getTargetLowering();
6582 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
6584 unsigned PreferredFusedOpcode =
6585 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6599 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6601 unsigned Flags =
MI.getFlags() & FpExtSrc->
getFlags();
6605 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6606 {FpExtX.getReg(0), FpExtY.getReg(0), RHS.Reg}, Flags);
6615 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6617 unsigned Flags =
MI.getFlags() & FpExtSrc->
getFlags();
6621 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6622 {FpExtX.getReg(0), FpExtY.getReg(0), LHS.Reg}, Flags);
6633 assert(
MI.getOpcode() == TargetOpcode::G_FADD);
6635 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6647 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6649 unsigned PreferredFusedOpcode =
6650 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6655 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6658 MRI.hasOneNonDBGUse(LHS.MI->getOperand(0).getReg()) &&
6659 MRI.hasOneNonDBGUse(LHS.MI->getOperand(3).getReg())) {
6664 else if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6667 MRI.hasOneNonDBGUse(RHS.MI->getOperand(0).getReg()) &&
6668 MRI.hasOneNonDBGUse(RHS.MI->getOperand(3).getReg())) {
6677 Register X = FMA->getOperand(1).getReg();
6678 Register Y = FMA->getOperand(2).getReg();
6681 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6682 unsigned OuterFlags =
MI.getFlags() & FMA->getFlags();
6685 Register InnerFMA =
MRI.createGenericVirtualRegister(DstTy);
6686 B.buildInstr(PreferredFusedOpcode, {InnerFMA}, {U, V, Z}, InnerFlags);
6687 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6688 {
X,
Y, InnerFMA}, OuterFlags);
6699 assert(
MI.getOpcode() == TargetOpcode::G_FADD);
6701 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6708 const auto &TLI = *
MI.getMF()->getSubtarget().getTargetLowering();
6709 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
6719 unsigned PreferredFusedOpcode =
6720 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6734 Register FpExtU =
B.buildFPExt(DstType, U).getReg(0);
6735 Register FpExtV =
B.buildFPExt(DstType, V).getReg(0);
6736 Register InnerFMA =
B.buildInstr(PreferredFusedOpcode, {DstType},
6737 {FpExtU, FpExtV, Z}, InnerFlags)
6739 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6740 {
X,
Y, InnerFMA}, OuterFlags);
6746 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6750 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6752 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6753 unsigned OuterFlags =
MI.getFlags() & LHS.MI->getFlags();
6757 LHS.MI->getOperand(1).getReg(),
6758 LHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags,
B);
6769 FMAMI->
getOpcode() == PreferredFusedOpcode) {
6774 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6776 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6777 unsigned OuterFlags =
MI.getFlags() & FMAMI->
getFlags();
6781 X =
B.buildFPExt(DstType,
X).getReg(0);
6782 Y =
B.buildFPExt(DstType,
Y).getReg(0);
6785 InnerFlags, OuterFlags,
B);
6794 if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6798 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6800 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6801 unsigned OuterFlags =
MI.getFlags() & RHS.MI->getFlags();
6805 RHS.MI->getOperand(1).getReg(),
6806 RHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags,
B);
6817 FMAMI->
getOpcode() == PreferredFusedOpcode) {
6822 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6824 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6825 unsigned OuterFlags =
MI.getFlags() & FMAMI->
getFlags();
6829 X =
B.buildFPExt(DstType,
X).getReg(0);
6830 Y =
B.buildFPExt(DstType,
Y).getReg(0);
6833 InnerFlags, OuterFlags,
B);
6845 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
6847 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6859 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6863 int FirstMulHasFewerUses =
true;
6867 FirstMulHasFewerUses =
false;
6869 unsigned PreferredFusedOpcode =
6870 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6873 if (FirstMulHasFewerUses &&
6876 unsigned Flags =
MI.getFlags() & LHS.MI->getFlags();
6878 Register NegZ =
B.buildFNeg(DstTy, RHS.Reg).getReg(0);
6879 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6880 {LHS.MI->getOperand(1).getReg(),
6881 LHS.MI->getOperand(2).getReg(), NegZ},
6889 unsigned Flags =
MI.getFlags() & RHS.MI->getFlags();
6892 B.buildFNeg(DstTy, RHS.MI->getOperand(1).getReg()).getReg(0);
6893 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6894 {NegY, RHS.MI->getOperand(2).getReg(), LHS.Reg}, Flags);
6905 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
6907 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6913 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6915 unsigned PreferredFusedOpcode =
6916 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6924 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
6928 Register NegZ =
B.buildFNeg(DstTy, RHSReg).getReg(0);
6929 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6940 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
6942 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6956 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
6958 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6964 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6966 unsigned PreferredFusedOpcode =
6967 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6974 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
6980 Register NegZ =
B.buildFNeg(DstTy, RHSReg).getReg(0);
6981 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6982 {FpExtX, FpExtY, NegZ}, Flags);
6991 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
6995 Register NegY =
B.buildFNeg(DstTy, FpExtY).getReg(0);
6998 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6999 {NegY, FpExtZ, LHSReg}, Flags);
7010 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
7012 bool AllowFusionGlobally, HasFMAD,
Aggressive;
7016 const auto &TLI = *
MI.getMF()->getSubtarget().getTargetLowering();
7017 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
7021 unsigned PreferredFusedOpcode =
7022 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
7026 Register FpExtX =
B.buildFPExt(DstTy,
X).getReg(0);
7027 Register FpExtY =
B.buildFPExt(DstTy,
Y).getReg(0);
7028 B.buildInstr(PreferredFusedOpcode, {Dst}, {FpExtX, FpExtY, Z}, Flags);
7039 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstTy,
7041 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
7043 Register FMAReg =
MRI.createGenericVirtualRegister(DstTy);
7046 B.buildFNeg(
MI.getOperand(0).getReg(), FMAReg);
7056 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstTy,
7058 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
7070 unsigned &IdxToPropagate)
const {
7072 switch (
MI.getOpcode()) {
7075 case TargetOpcode::G_FMINNUM:
7076 case TargetOpcode::G_FMAXNUM:
7077 PropagateNaN =
false;
7079 case TargetOpcode::G_FMINIMUM:
7080 case TargetOpcode::G_FMAXIMUM:
7081 PropagateNaN =
true;
7085 auto MatchNaN = [&](
unsigned Idx) {
7086 Register MaybeNaNReg =
MI.getOperand(Idx).getReg();
7090 IdxToPropagate = PropagateNaN ? Idx : (Idx == 1 ? 2 : 1);
7094 return MatchNaN(1) || MatchNaN(2);
7102 assert(
MI.getOpcode() == TargetOpcode::G_FDIV);
7112 return N0CFP && (N0CFP->isOne() || N0CFP->isMinusOne());
7129 for (
auto &U :
MRI.use_nodbg_instructions(
Y)) {
7130 if (&U == &
MI || U.getParent() !=
MI.getParent())
7132 if (U.getOpcode() == TargetOpcode::G_FDIV &&
7133 U.getOperand(2).getReg() ==
Y && U.getOperand(1).getReg() !=
Y &&
7134 !IsOne(U.getOperand(1).getReg())) {
7147 return MatchInfo.
size() >= MinUses;
7155 LLT Ty =
MRI.getType(MatchInfo[0]->getOperand(0).
getReg());
7156 auto Div =
Builder.buildFDiv(Ty,
Builder.buildFConstant(Ty, 1.0),
7157 MatchInfo[0]->getOperand(2).getReg(),
7158 MatchInfo[0]->getFlags());
7163 Builder.buildFMul(
MI->getOperand(0).getReg(),
MI->getOperand(1).getReg(),
7164 Div->getOperand(0).getReg(),
MI->getFlags());
7165 MI->eraseFromParent();
7170 assert(
MI.getOpcode() == TargetOpcode::G_ADD &&
"Expected a G_ADD");
7180 Reg == MaybeSameReg;
7182 return CheckFold(LHS, RHS) || CheckFold(RHS, LHS);
7203 LLT DstVecTy =
MRI.getType(
MI.getOperand(0).getReg());
7212 return MRI.getType(MatchInfo) == DstVecTy;
7215 std::optional<ValueAndVReg> ShiftAmount;
7224 return MRI.getType(MatchInfo) == DstVecTy;
7239 return MRI.getType(MatchInfo) ==
MRI.getType(
MI.getOperand(0).getReg());
7246 std::optional<ValueAndVReg> ShiftAmt;
7252 LLT MatchTy =
MRI.getType(MatchInfo);
7253 return ShiftAmt->Value.getZExtValue() == MatchTy.
getSizeInBits() &&
7254 MatchTy ==
MRI.getType(
MI.getOperand(0).getReg());
7257unsigned CombinerHelper::getFPMinMaxOpcForSelect(
7259 SelectPatternNaNBehaviour VsNaNRetVal)
const {
7260 assert(VsNaNRetVal != SelectPatternNaNBehaviour::NOT_APPLICABLE &&
7261 "Expected a NaN behaviour?");
7271 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7272 return TargetOpcode::G_FMAXNUM;
7273 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7274 return TargetOpcode::G_FMAXIMUM;
7275 if (
isLegal({TargetOpcode::G_FMAXNUM, {DstTy}}))
7276 return TargetOpcode::G_FMAXNUM;
7277 if (
isLegal({TargetOpcode::G_FMAXIMUM, {DstTy}}))
7278 return TargetOpcode::G_FMAXIMUM;
7284 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7285 return TargetOpcode::G_FMINNUM;
7286 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7287 return TargetOpcode::G_FMINIMUM;
7288 if (
isLegal({TargetOpcode::G_FMINNUM, {DstTy}}))
7289 return TargetOpcode::G_FMINNUM;
7290 if (!
isLegal({TargetOpcode::G_FMINIMUM, {DstTy}}))
7292 return TargetOpcode::G_FMINIMUM;
7296CombinerHelper::SelectPatternNaNBehaviour
7298 bool IsOrderedComparison)
const {
7299 bool LHSSafe =
VT->isKnownNeverNaN(
LHS);
7300 bool RHSSafe =
VT->isKnownNeverNaN(
RHS);
7302 if (!LHSSafe && !RHSSafe)
7303 return SelectPatternNaNBehaviour::NOT_APPLICABLE;
7304 if (LHSSafe && RHSSafe)
7305 return SelectPatternNaNBehaviour::RETURNS_ANY;
7308 if (IsOrderedComparison)
7309 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_NAN
7310 : SelectPatternNaNBehaviour::RETURNS_OTHER;
7313 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_OTHER
7314 : SelectPatternNaNBehaviour::RETURNS_NAN;
7323 LLT DstTy =
MRI.getType(Dst);
7336 SelectPatternNaNBehaviour ResWithKnownNaNInfo =
7338 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::NOT_APPLICABLE)
7340 if (TrueVal == CmpRHS && FalseVal == CmpLHS) {
7343 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_NAN)
7344 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_OTHER;
7345 else if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_OTHER)
7346 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_NAN;
7348 if (TrueVal != CmpLHS || FalseVal != CmpRHS)
7351 unsigned Opc = getFPMinMaxOpcForSelect(Pred, DstTy, ResWithKnownNaNInfo);
7356 if (
Opc != TargetOpcode::G_FMAXIMUM &&
Opc != TargetOpcode::G_FMINIMUM) {
7361 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero()) {
7363 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero())
7367 MatchInfo = [=](MachineIRBuilder &
B) {
7368 B.buildInstr(
Opc, {Dst}, {CmpLHS, CmpRHS});
7376 assert(
MI.getOpcode() == TargetOpcode::G_SELECT);
7383 Register TrueVal =
MI.getOperand(2).getReg();
7384 Register FalseVal =
MI.getOperand(3).getReg();
7385 return matchFPSelectToMinMax(Dst,
Cond, TrueVal, FalseVal, MatchInfo);
7390 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
7403 if (MatchedSub &&
X != OpLHS)
7411 Y =
X == OpLHS ? OpRHS :
X == OpRHS ? OpLHS :
Register();
7414 auto Zero =
B.buildConstant(
MRI.getType(
Y), 0);
7415 B.buildICmp(Pred, Dst,
Y, Zero);
7422static std::optional<unsigned>
7424 std::optional<int64_t> &Result) {
7425 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR ||
7426 Opcode == TargetOpcode::G_ASHR) &&
7427 "Expect G_SHL, G_LSHR or G_ASHR.");
7428 auto SignificantBits = 0;
7430 case TargetOpcode::G_SHL:
7434 case TargetOpcode::G_LSHR:
7438 case TargetOpcode::G_ASHR:
7447 Result = std::nullopt;
7458 Register ShiftVal =
MI.getOperand(1).getReg();
7459 Register ShiftReg =
MI.getOperand(2).getReg();
7460 LLT ResTy =
MRI.getType(
MI.getOperand(0).getReg());
7461 auto IsShiftTooBig = [&](
const Constant *
C) {
7466 MatchInfo = std::nullopt;
7470 MI.getOpcode(), MatchInfo);
7471 return OptMaxUsefulShift && CI->uge(*OptMaxUsefulShift);
7477 unsigned LHSOpndIdx = 1;
7478 unsigned RHSOpndIdx = 2;
7479 switch (
MI.getOpcode()) {
7480 case TargetOpcode::G_UADDO:
7481 case TargetOpcode::G_SADDO:
7482 case TargetOpcode::G_UMULO:
7483 case TargetOpcode::G_SMULO:
7490 Register LHS =
MI.getOperand(LHSOpndIdx).getReg();
7491 Register RHS =
MI.getOperand(RHSOpndIdx).getReg();
7501 if (LHSDef->
getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER)
7505 return RHSDef->
getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER &&
7512 std::optional<FPValueAndVReg> ValAndVReg;
7520 unsigned LHSOpndIdx = 1;
7521 unsigned RHSOpndIdx = 2;
7522 switch (
MI.getOpcode()) {
7523 case TargetOpcode::G_UADDO:
7524 case TargetOpcode::G_SADDO:
7525 case TargetOpcode::G_UMULO:
7526 case TargetOpcode::G_SMULO:
7533 Register LHSReg =
MI.getOperand(LHSOpndIdx).getReg();
7534 Register RHSReg =
MI.getOperand(RHSOpndIdx).getReg();
7535 MI.getOperand(LHSOpndIdx).setReg(RHSReg);
7536 MI.getOperand(RHSOpndIdx).setReg(LHSReg);
7540bool CombinerHelper::isOneOrOneSplat(
Register Src,
bool AllowUndefs)
const {
7542 if (SrcTy.isFixedVector())
7544 if (SrcTy.isScalar()) {
7548 return IConstant && IConstant->Value == 1;
7553bool CombinerHelper::isZeroOrZeroSplat(
Register Src,
bool AllowUndefs)
const {
7554 LLT SrcTy =
MRI.getType(Src);
7556 return isConstantSplatVector(Src, 0, AllowUndefs);
7561 return IConstant && IConstant->Value == 0;
7568bool CombinerHelper::isConstantSplatVector(
Register Src, int64_t SplatValue,
7569 bool AllowUndefs)
const {
7575 for (
unsigned I = 0;
I < NumSources; ++
I) {
7576 GImplicitDef *ImplicitDef =
7578 if (ImplicitDef && AllowUndefs)
7580 if (ImplicitDef && !AllowUndefs)
7582 std::optional<ValueAndVReg> IConstant =
7584 if (IConstant && IConstant->Value == SplatValue)
7594CombinerHelper::getConstantOrConstantSplatVector(
Register Src)
const {
7597 return IConstant->Value;
7601 return std::nullopt;
7604 std::optional<APInt>
Value = std::nullopt;
7605 for (
unsigned I = 0;
I < NumSources; ++
I) {
7606 std::optional<ValueAndVReg> IConstant =
7609 return std::nullopt;
7611 Value = IConstant->Value;
7612 else if (*
Value != IConstant->Value)
7613 return std::nullopt;
7619bool CombinerHelper::isConstantOrConstantVectorI(
Register Src)
const {
7629 for (
unsigned I = 0;
I < NumSources; ++
I) {
7630 std::optional<ValueAndVReg> IConstant =
7639bool CombinerHelper::tryFoldSelectOfConstants(
GSelect *
Select,
7646 LLT CondTy =
MRI.getType(
Select->getCondReg());
7647 LLT TrueTy =
MRI.getType(
Select->getTrueReg());
7657 std::optional<ValueAndVReg> TrueOpt =
7659 std::optional<ValueAndVReg> FalseOpt =
7662 if (!TrueOpt || !FalseOpt)
7665 APInt TrueValue = TrueOpt->Value;
7666 APInt FalseValue = FalseOpt->Value;
7670 MatchInfo = [=](MachineIRBuilder &
B) {
7671 B.setInstrAndDebugLoc(*
Select);
7672 B.buildZExtOrTrunc(Dest,
Cond);
7679 MatchInfo = [=](MachineIRBuilder &
B) {
7680 B.setInstrAndDebugLoc(*
Select);
7681 B.buildSExtOrTrunc(Dest,
Cond);
7688 MatchInfo = [=](MachineIRBuilder &
B) {
7689 B.setInstrAndDebugLoc(*
Select);
7690 Register Inner =
MRI.createGenericVirtualRegister(CondTy);
7691 B.buildNot(Inner,
Cond);
7692 B.buildZExtOrTrunc(Dest, Inner);
7699 MatchInfo = [=](MachineIRBuilder &
B) {
7700 B.setInstrAndDebugLoc(*
Select);
7701 Register Inner =
MRI.createGenericVirtualRegister(CondTy);
7702 B.buildNot(Inner,
Cond);
7703 B.buildSExtOrTrunc(Dest, Inner);
7709 if (TrueValue - 1 == FalseValue) {
7710 MatchInfo = [=](MachineIRBuilder &
B) {
7711 B.setInstrAndDebugLoc(*
Select);
7712 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7713 B.buildZExtOrTrunc(Inner,
Cond);
7714 B.buildAdd(Dest, Inner, False);
7720 if (TrueValue + 1 == FalseValue) {
7721 MatchInfo = [=](MachineIRBuilder &
B) {
7722 B.setInstrAndDebugLoc(*
Select);
7723 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7724 B.buildSExtOrTrunc(Inner,
Cond);
7725 B.buildAdd(Dest, Inner, False);
7732 MatchInfo = [=](MachineIRBuilder &
B) {
7733 B.setInstrAndDebugLoc(*
Select);
7734 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7735 B.buildZExtOrTrunc(Inner,
Cond);
7738 auto ShAmtC =
B.buildConstant(ShiftTy, TrueValue.
exactLogBase2());
7739 B.buildShl(Dest, Inner, ShAmtC, Flags);
7746 MatchInfo = [=](MachineIRBuilder &
B) {
7747 B.setInstrAndDebugLoc(*
Select);
7749 B.buildNot(Not,
Cond);
7750 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7751 B.buildZExtOrTrunc(Inner, Not);
7754 auto ShAmtC =
B.buildConstant(ShiftTy, FalseValue.
exactLogBase2());
7755 B.buildShl(Dest, Inner, ShAmtC, Flags);
7762 MatchInfo = [=](MachineIRBuilder &
B) {
7763 B.setInstrAndDebugLoc(*
Select);
7764 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7765 B.buildSExtOrTrunc(Inner,
Cond);
7766 B.buildOr(Dest, Inner, False, Flags);
7773 MatchInfo = [=](MachineIRBuilder &
B) {
7774 B.setInstrAndDebugLoc(*
Select);
7776 B.buildNot(Not,
Cond);
7777 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7778 B.buildSExtOrTrunc(Inner, Not);
7779 B.buildOr(Dest, Inner, True, Flags);
7788bool CombinerHelper::tryFoldBoolSelectToLogic(
GSelect *
Select,
7795 LLT CondTy =
MRI.getType(
Select->getCondReg());
7796 LLT TrueTy =
MRI.getType(
Select->getTrueReg());
7805 if (CondTy != TrueTy)
7810 if ((
Cond == True) || isOneOrOneSplat(True,
true)) {
7811 MatchInfo = [=](MachineIRBuilder &
B) {
7812 B.setInstrAndDebugLoc(*
Select);
7813 Register Ext =
MRI.createGenericVirtualRegister(TrueTy);
7814 B.buildZExtOrTrunc(Ext,
Cond);
7815 auto FreezeFalse =
B.buildFreeze(TrueTy, False);
7816 B.buildOr(DstReg, Ext, FreezeFalse, Flags);
7823 if ((
Cond == False) || isZeroOrZeroSplat(False,
true)) {
7824 MatchInfo = [=](MachineIRBuilder &
B) {
7825 B.setInstrAndDebugLoc(*
Select);
7826 Register Ext =
MRI.createGenericVirtualRegister(TrueTy);
7827 B.buildZExtOrTrunc(Ext,
Cond);
7828 auto FreezeTrue =
B.buildFreeze(TrueTy, True);
7829 B.buildAnd(DstReg, Ext, FreezeTrue);
7835 if (isOneOrOneSplat(False,
true)) {
7836 MatchInfo = [=](MachineIRBuilder &
B) {
7837 B.setInstrAndDebugLoc(*
Select);
7839 Register Inner =
MRI.createGenericVirtualRegister(CondTy);
7840 B.buildNot(Inner,
Cond);
7842 Register Ext =
MRI.createGenericVirtualRegister(TrueTy);
7843 B.buildZExtOrTrunc(Ext, Inner);
7844 auto FreezeTrue =
B.buildFreeze(TrueTy, True);
7845 B.buildOr(DstReg, Ext, FreezeTrue, Flags);
7851 if (isZeroOrZeroSplat(True,
true)) {
7852 MatchInfo = [=](MachineIRBuilder &
B) {
7853 B.setInstrAndDebugLoc(*
Select);
7855 Register Inner =
MRI.createGenericVirtualRegister(CondTy);
7856 B.buildNot(Inner,
Cond);
7858 Register Ext =
MRI.createGenericVirtualRegister(TrueTy);
7859 B.buildZExtOrTrunc(Ext, Inner);
7860 auto FreezeFalse =
B.buildFreeze(TrueTy, False);
7861 B.buildAnd(DstReg, Ext, FreezeFalse);
7883 LLT DstTy =
MRI.getType(DstReg);
7888 if (!
MRI.hasOneNonDBGUse(CondReg))
7897 if (True == CmpRHS && False == CmpLHS) {
7905 if (True != CmpLHS || False != CmpRHS)
7945 assert(
MI.getOpcode() == TargetOpcode::G_SUB);
7946 Register DestReg =
MI.getOperand(0).getReg();
7947 LLT DestTy =
MRI.getType(DestReg);
7961 if (
isLegal({NewOpc, {DestTy}})) {
7963 B.buildInstr(NewOpc, {DestReg}, {
X, Sub0});
7975 if (tryFoldSelectOfConstants(
Select, MatchInfo))
7978 if (tryFoldBoolSelectToLogic(
Select, MatchInfo))
7988bool CombinerHelper::tryFoldAndOrOrICmpsUsingRanges(
7990 assert(Logic->
getOpcode() != TargetOpcode::G_XOR &&
"unexpected xor");
7991 bool IsAnd = Logic->
getOpcode() == TargetOpcode::G_AND;
7995 unsigned Flags = Logic->
getFlags();
8014 std::optional<ValueAndVReg> MaybeC1 =
8018 C1 = MaybeC1->Value;
8020 std::optional<ValueAndVReg> MaybeC2 =
8024 C2 = MaybeC2->Value;
8045 std::optional<APInt> Offset1;
8046 std::optional<APInt> Offset2;
8049 std::optional<ValueAndVReg> MaybeOffset1 =
8052 R1 =
Add->getLHSReg();
8053 Offset1 = MaybeOffset1->Value;
8057 std::optional<ValueAndVReg> MaybeOffset2 =
8060 R2 =
Add->getLHSReg();
8061 Offset2 = MaybeOffset2->Value;
8080 bool CreateMask =
false;
8093 if (!LowerDiff.
isPowerOf2() || LowerDiff != UpperDiff ||
8106 CR->getEquivalentICmp(NewPred, NewC,
Offset);
8115 MatchInfo = [=](MachineIRBuilder &
B) {
8116 if (CreateMask &&
Offset != 0) {
8117 auto TildeLowerDiff =
B.buildConstant(CmpOperandTy, ~LowerDiff);
8118 auto And =
B.buildAnd(CmpOperandTy, R1, TildeLowerDiff);
8119 auto OffsetC =
B.buildConstant(CmpOperandTy,
Offset);
8120 auto Add =
B.buildAdd(CmpOperandTy,
And, OffsetC, Flags);
8121 auto NewCon =
B.buildConstant(CmpOperandTy, NewC);
8122 auto ICmp =
B.buildICmp(NewPred, CmpTy,
Add, NewCon);
8123 B.buildZExtOrTrunc(DstReg, ICmp);
8124 }
else if (CreateMask &&
Offset == 0) {
8125 auto TildeLowerDiff =
B.buildConstant(CmpOperandTy, ~LowerDiff);
8126 auto And =
B.buildAnd(CmpOperandTy, R1, TildeLowerDiff);
8127 auto NewCon =
B.buildConstant(CmpOperandTy, NewC);
8128 auto ICmp =
B.buildICmp(NewPred, CmpTy,
And, NewCon);
8129 B.buildZExtOrTrunc(DstReg, ICmp);
8130 }
else if (!CreateMask &&
Offset != 0) {
8131 auto OffsetC =
B.buildConstant(CmpOperandTy,
Offset);
8132 auto Add =
B.buildAdd(CmpOperandTy, R1, OffsetC, Flags);
8133 auto NewCon =
B.buildConstant(CmpOperandTy, NewC);
8134 auto ICmp =
B.buildICmp(NewPred, CmpTy,
Add, NewCon);
8135 B.buildZExtOrTrunc(DstReg, ICmp);
8136 }
else if (!CreateMask &&
Offset == 0) {
8137 auto NewCon =
B.buildConstant(CmpOperandTy, NewC);
8138 auto ICmp =
B.buildICmp(NewPred, CmpTy, R1, NewCon);
8139 B.buildZExtOrTrunc(DstReg, ICmp);
8147bool CombinerHelper::tryFoldLogicOfFCmps(
GLogicalBinOp *Logic,
8153 bool IsAnd = Logic->
getOpcode() == TargetOpcode::G_AND;
8165 LLT CmpTy =
MRI.getType(Cmp1->
getReg(0));
8171 {TargetOpcode::G_FCMP, {CmpTy, CmpOperandTy}}) ||
8172 !
MRI.hasOneNonDBGUse(Logic->
getReg(0)) ||
8173 !
MRI.hasOneNonDBGUse(Cmp1->
getReg(0)) ||
8174 !
MRI.hasOneNonDBGUse(Cmp2->
getReg(0)) ||
8185 if (LHS0 == RHS1 && LHS1 == RHS0) {
8191 if (LHS0 == RHS0 && LHS1 == RHS1) {
8195 unsigned NewPred = IsAnd ? CmpCodeL & CmpCodeR : CmpCodeL | CmpCodeR;
8197 MatchInfo = [=](MachineIRBuilder &
B) {
8202 auto False =
B.buildConstant(CmpTy, 0);
8203 B.buildZExtOrTrunc(DestReg, False);
8210 B.buildZExtOrTrunc(DestReg, True);
8212 auto Cmp =
B.buildFCmp(Pred, CmpTy, LHS0, LHS1, Flags);
8213 B.buildZExtOrTrunc(DestReg, Cmp);
8225 if (tryFoldAndOrOrICmpsUsingRanges(
And, MatchInfo))
8228 if (tryFoldLogicOfFCmps(
And, MatchInfo))
8237 if (tryFoldAndOrOrICmpsUsingRanges(
Or, MatchInfo))
8240 if (tryFoldLogicOfFCmps(
Or, MatchInfo))
8255 bool IsSigned =
Add->isSigned();
8256 LLT DstTy =
MRI.getType(Dst);
8257 LLT CarryTy =
MRI.getType(Carry);
8260 if (
MRI.use_nodbg_empty(Carry) &&
8263 B.buildAdd(Dst, LHS, RHS);
8264 B.buildUndef(Carry);
8270 if (isConstantOrConstantVectorI(LHS) && !isConstantOrConstantVectorI(RHS)) {
8273 B.buildSAddo(Dst, Carry, RHS, LHS);
8279 B.buildUAddo(Dst, Carry, RHS, LHS);
8284 std::optional<APInt> MaybeLHS = getConstantOrConstantSplatVector(LHS);
8285 std::optional<APInt> MaybeRHS = getConstantOrConstantSplatVector(RHS);
8291 APInt Result = IsSigned ? MaybeLHS->sadd_ov(*MaybeRHS, Overflow)
8292 : MaybeLHS->uadd_ov(*MaybeRHS, Overflow);
8294 B.buildConstant(Dst, Result);
8295 B.buildConstant(Carry, Overflow);
8303 B.buildCopy(Dst, LHS);
8304 B.buildConstant(Carry, 0);
8313 if (MaybeRHS && AddLHS &&
MRI.hasOneNonDBGUse(
Add->getReg(0)) &&
8316 std::optional<APInt> MaybeAddRHS =
8317 getConstantOrConstantSplatVector(AddLHS->
getRHSReg());
8320 APInt NewC = IsSigned ? MaybeAddRHS->sadd_ov(*MaybeRHS, Overflow)
8321 : MaybeAddRHS->uadd_ov(*MaybeRHS, Overflow);
8325 auto ConstRHS =
B.buildConstant(DstTy, NewC);
8326 B.buildSAddo(Dst, Carry, AddLHS->
getLHSReg(), ConstRHS);
8332 auto ConstRHS =
B.buildConstant(DstTy, NewC);
8333 B.buildUAddo(Dst, Carry, AddLHS->
getLHSReg(), ConstRHS);
8358 B.buildConstant(Carry, 0);
8365 B.buildAdd(Dst, LHS, RHS);
8366 B.buildConstant(Carry, 1);
8378 if (
VT->computeNumSignBits(RHS) > 1 &&
VT->computeNumSignBits(LHS) > 1) {
8381 B.buildConstant(Carry, 0);
8397 B.buildConstant(Carry, 0);
8404 B.buildAdd(Dst, LHS, RHS);
8405 B.buildConstant(Carry, 1);
8423 bool OptForSize =
MI.getMF()->getFunction().hasOptSize();
8429 auto [Dst,
Base] =
MI.getFirst2Regs();
8430 LLT Ty =
MRI.getType(Dst);
8434 Builder.buildFConstant(Dst, 1.0);
8435 MI.removeFromParent();
8447 std::optional<SrcOp> Res;
8449 while (ExpVal > 0) {
8454 Res =
Builder.buildFMul(Ty, *Res, CurSquare);
8457 CurSquare =
Builder.buildFMul(Ty, CurSquare, CurSquare);
8464 Res =
Builder.buildFDiv(Ty,
Builder.buildFConstant(Ty, 1.0), *Res,
8468 MI.eraseFromParent();
8479 if (!
MRI.hasOneNonDBGUse(
Sub->getLHSReg()))
8486 LLT DstTy =
MRI.getType(Dst);
8489 auto Const =
B.buildConstant(DstTy, C1 - C2);
8490 B.buildAdd(Dst,
A, Const);
8504 if (!
MRI.hasOneNonDBGUse(
Sub->getRHSReg()))
8511 LLT DstTy =
MRI.getType(Dst);
8514 auto Const =
B.buildConstant(DstTy, C2 - C1);
8515 B.buildSub(Dst, Const,
A);
8536 LLT DstTy =
MRI.getType(Dst);
8539 auto Const =
B.buildConstant(DstTy, C1 + C2);
8540 B.buildSub(Dst,
A, Const);
8561 LLT DstTy =
MRI.getType(Dst);
8564 auto Const =
B.buildConstant(DstTy, C1 - C2);
8565 B.buildSub(Dst, Const,
A);
8579 if (!
MRI.hasOneNonDBGUse(
Add->getLHSReg()))
8586 LLT DstTy =
MRI.getType(Dst);
8589 auto Const =
B.buildConstant(DstTy, C2 - C1);
8590 B.buildAdd(Dst,
A, Const);
8634 if (!
MRI.hasOneNonDBGUse(BV->
getReg(0)))
8642 LLT SmallBvTy = DstTy;
8646 {TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
8651 {TargetOpcode::G_ANYEXT,
8663 auto AnyExt =
B.buildAnyExt(SmallBvElemenTy, SourceArray);
8664 Ops.push_back(AnyExt.getReg(0));
8682 const LLT SrcTy =
MRI.getType(Shuffle.getSrc1Reg());
8683 const unsigned NumSrcElems = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
8684 const unsigned NumDstElts = OrigMask.
size();
8685 for (
unsigned i = 0; i != NumDstElts; ++i) {
8686 int Idx = OrigMask[i];
8687 if (Idx >= (
int)NumSrcElems) {
8698 B.buildShuffleVector(
MI.getOperand(0),
MI.getOperand(1),
MI.getOperand(2),
8699 std::move(NewMask));
8706 const unsigned MaskSize = Mask.size();
8707 for (
unsigned I = 0;
I < MaskSize; ++
I) {
8712 if (Idx < (
int)NumElems)
8713 Mask[
I] = Idx + NumElems;
8715 Mask[
I] = Idx - NumElems;
8725 if (
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(),
MRI))
8728 if (
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(),
MRI))
8731 const LLT DstTy =
MRI.getType(Shuffle.getReg(0));
8732 const LLT Src1Ty =
MRI.getType(Shuffle.getSrc1Reg());
8734 {TargetOpcode::G_SHUFFLE_VECTOR, {DstTy, Src1Ty}}))
8738 const unsigned NumSrcElems = Src1Ty.getNumElements();
8740 bool TouchesSrc1 =
false;
8741 bool TouchesSrc2 =
false;
8742 const unsigned NumElems = Mask.size();
8743 for (
unsigned Idx = 0; Idx < NumElems; ++Idx) {
8747 if (Mask[Idx] < (
int)NumSrcElems)
8753 if (TouchesSrc1 == TouchesSrc2)
8756 Register NewSrc1 = Shuffle.getSrc1Reg();
8759 NewSrc1 = Shuffle.getSrc2Reg();
8764 auto Undef =
B.buildUndef(Src1Ty);
8765 B.buildShuffleVector(Shuffle.getReg(0), NewSrc1,
Undef, NewMask);
8779 LLT DstTy =
MRI.getType(Dst);
8780 LLT CarryTy =
MRI.getType(Carry);
8802 B.buildConstant(Carry, 0);
8809 B.buildSub(Dst, LHS, RHS);
8827 B.buildConstant(Carry, 0);
8834 B.buildSub(Dst, LHS, RHS);
8851 CtlzMI.
getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON) &&
8852 "Expected G_CTLZ variant");
8857 LLT Ty =
MRI.getType(Dst);
8858 LLT SrcTy =
MRI.getType(Src);
8860 if (!(Ty.isValid() && Ty.isScalar()))
8869 switch (
LI->getAction(Query).Action) {
8880 bool NeedAdd =
true;
8888 unsigned BitWidth = Ty.getScalarSizeInBits();
8899 B.buildCTLS(Dst,
X);
8903 auto Ctls =
B.buildCTLS(Ty,
X);
8904 auto One =
B.buildConstant(Ty, 1);
8906 B.buildAdd(Dst, Ctls, One);
8916 unsigned TargetOpc)
const {
8917 assert((
MI.getOpcode() == TargetOpcode::G_LSHR ||
8918 MI.getOpcode() == TargetOpcode::G_ASHR) &&
8919 "Expected G_LSHR/G_ASHR");
8922 return XTy ==
MRI.getType(
Y) &&
isLegal({TargetOpc, {XTy}});
8926 assert((
MI.getOpcode() == TargetOpcode::G_CTLZ ||
8927 MI.getOpcode() == TargetOpcode::G_CTTZ) &&
8928 "Expected count-zero opcode");
8929 switch (
MI.getOpcode()) {
8930 case TargetOpcode::G_CTLZ:
8931 return TargetOpcode::G_CTLZ_ZERO_POISON;
8932 case TargetOpcode::G_CTTZ:
8933 return TargetOpcode::G_CTTZ_ZERO_POISON;
8945 if (!
VT->isKnownNeverZero(Src))
8948 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
8949 LLT SrcTy =
MRI.getType(Src);