129static std::optional<bool>
133 unsigned Width = MemOffset2Idx.
size();
136 bool BigEndian =
true, LittleEndian =
true;
137 for (
unsigned MemOffset = 0; MemOffset < Width; ++ MemOffset) {
138 auto MemOffsetAndIdx = MemOffset2Idx.
find(MemOffset);
139 if (MemOffsetAndIdx == MemOffset2Idx.
end())
141 const int64_t Idx = MemOffsetAndIdx->second - LowestIdx;
142 assert(Idx >= 0 &&
"Expected non-negative byte offset?");
145 if (!BigEndian && !LittleEndian)
149 assert((BigEndian != LittleEndian) &&
150 "Pattern cannot be both big and little endian!");
157 assert(
LI &&
"Must have LegalizerInfo to query isLegal!");
185 return isLegal({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}}) &&
186 isLegal({TargetOpcode::G_CONSTANT, {EltTy}});
193 if (
MRI.constrainRegAttrs(ToReg, FromReg))
194 MRI.replaceRegWith(FromReg, ToReg);
196 Builder.buildCopy(FromReg, ToReg);
198 Observer.finishedChangingAllUsesOfReg();
213 unsigned ToOpcode)
const {
228 MRI.setRegBank(Reg, *RegBank);
239 if (
MI.getOpcode() != TargetOpcode::COPY)
249 MI.eraseFromParent();
254 assert(
MI.getOpcode() == TargetOpcode::G_FREEZE &&
"Invalid instruction");
260 if (!
MRI.hasOneNonDBGUse(OrigOp))
281 std::optional<MachineOperand> MaybePoisonOperand;
283 if (!Operand.isReg())
289 if (!MaybePoisonOperand)
290 MaybePoisonOperand = Operand;
299 if (!MaybePoisonOperand) {
304 B.buildCopy(
DstOp, OrigOp);
309 Register MaybePoisonOperandReg = MaybePoisonOperand->getReg();
310 LLT MaybePoisonOperandRegTy =
MRI.getType(MaybePoisonOperandReg);
313 {TargetOpcode::G_FREEZE, {MaybePoisonOperandRegTy}}))
321 auto Freeze =
B.buildFreeze(MaybePoisonOperandRegTy, MaybePoisonOperandReg);
332 assert(
MI.getOpcode() == TargetOpcode::G_CONCAT_VECTORS &&
333 "Invalid instruction");
345 if (!
MRI.hasOneNonDBGUse(Reg))
347 switch (Def->getOpcode()) {
348 case TargetOpcode::G_BUILD_VECTOR:
353 Ops.push_back(BuildVecMO.getReg());
355 case TargetOpcode::G_IMPLICIT_DEF: {
356 LLT OpType =
MRI.getType(Reg);
363 OpType.getScalarType() &&
364 "All undefs should have the same type");
367 for (
unsigned EltIdx = 0, EltEnd = OpType.getNumElements();
368 EltIdx != EltEnd; ++EltIdx)
369 Ops.push_back(
Undef->getOperand(0).getReg());
378 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
380 {TargetOpcode::G_BUILD_VECTOR, {DstTy,
MRI.getType(
Ops[0])}})) {
395 Register NewDstReg =
MRI.cloneVirtualRegister(DstReg);
408 MI.eraseFromParent();
417 if (!Unmerge || Unmerge->
getReg(0) != BV.getSourceReg(0))
422 LLT InputTy =
MRI.getType(BCSrc);
424 if (!InputTy.
isScalar() || BV.getNumSources() % Factor != 0)
429 if (!
isLegal({TargetOpcode::G_BUILD_VECTOR, {BVDstTy, InputTy}}))
433 for (
unsigned Idx = 0; Idx < BV.getNumSources(); Idx += Factor) {
449 Ops.push_back(BCSrc);
470 auto BV =
Builder.buildBuildVector(BVDstTy,
Ops);
471 Builder.buildBitcast(
MI.getOperand(0).getReg(), BV);
472 MI.eraseFromParent();
478 Register SrcVec1 = Shuffle.getSrc1Reg();
479 Register SrcVec2 = Shuffle.getSrc2Reg();
480 LLT EltTy =
MRI.getType(SrcVec1).getElementType();
481 int Width =
MRI.getType(SrcVec1).getNumElements();
483 auto Unmerge1 =
Builder.buildUnmerge(EltTy, SrcVec1);
484 auto Unmerge2 =
Builder.buildUnmerge(EltTy, SrcVec2);
488 for (
int Val : Shuffle.getMask()) {
491 else if (Val < Width)
492 Extracts.
push_back(Unmerge1.getReg(Val));
494 Extracts.
push_back(Unmerge2.getReg(Val - Width));
496 assert(Extracts.
size() > 0 &&
"Expected at least one element in the shuffle");
497 if (Extracts.
size() == 1)
498 Builder.buildCopy(
MI.getOperand(0).getReg(), Extracts[0]);
500 Builder.buildBuildVector(
MI.getOperand(0).getReg(), Extracts);
501 MI.eraseFromParent();
518 LLT ShuffleSrcTy1 =
MRI.getType(
MI.getOperand(1).getReg());
520 for (
unsigned i = 0; i < Mask.size(); i += ConcatSrcNumElt) {
524 for (
unsigned j = 1; j < ConcatSrcNumElt; j++) {
525 if (i + j >= Mask.size())
527 if (Mask[i + j] != -1)
531 {TargetOpcode::G_IMPLICIT_DEF, {ConcatSrcTy}}))
534 }
else if (Mask[i] % ConcatSrcNumElt == 0) {
535 for (
unsigned j = 1; j < ConcatSrcNumElt; j++) {
536 if (i + j >= Mask.size())
538 if (Mask[i + j] != Mask[i] +
static_cast<int>(j))
555 {TargetOpcode::G_CONCAT_VECTORS,
556 {
MRI.getType(
MI.getOperand(0).getReg()), ConcatSrcTy}}))
567 SrcTy =
MRI.getType(Reg);
569 assert(SrcTy.isValid() &&
"Unexpected full undef vector in concat combine");
576 UndefReg =
Builder.buildUndef(SrcTy).getReg(0);
582 Builder.buildConcatVectors(
MI.getOperand(0).getReg(),
Ops);
585 MI.eraseFromParent();
590 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR &&
591 "Invalid instruction kind");
592 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
594 LLT SrcType =
MRI.getType(Src1);
596 unsigned DstNumElts = DstType.getNumElements();
597 unsigned SrcNumElts = SrcType.getNumElements();
614 if (DstNumElts < 2 * SrcNumElts)
619 if (DstNumElts % SrcNumElts != 0)
625 unsigned NumConcat = DstNumElts / SrcNumElts;
628 for (
unsigned i = 0; i != DstNumElts; ++i) {
635 if ((Idx % SrcNumElts != (i % SrcNumElts)) ||
636 (ConcatSrcs[i / SrcNumElts] >= 0 &&
637 ConcatSrcs[i / SrcNumElts] != (
int)(Idx / SrcNumElts)))
640 ConcatSrcs[i / SrcNumElts] = Idx / SrcNumElts;
647 for (
auto Src : ConcatSrcs) {
651 UndefReg =
Builder.buildUndef(SrcType).getReg(0);
653 Ops.push_back(UndefReg);
666 Register NewDstReg =
MRI.cloneVirtualRegister(DstReg);
674 MI.eraseFromParent();
683 const LLT TyForCandidate,
684 unsigned OpcodeForCandidate,
689 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
700 if (OpcodeForCandidate == TargetOpcode::G_ANYEXT &&
703 else if (CurrentUse.
ExtendOpcode == TargetOpcode::G_ANYEXT &&
704 OpcodeForCandidate != TargetOpcode::G_ANYEXT)
705 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
713 OpcodeForCandidate == TargetOpcode::G_ZEXT)
715 else if (CurrentUse.
ExtendOpcode == TargetOpcode::G_ZEXT &&
716 OpcodeForCandidate == TargetOpcode::G_SEXT)
717 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
726 return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
737static void InsertInsnsWithoutSideEffectsBeforeUse(
749 InsertBB = PredBB->
getMBB();
754 if (InsertBB ==
DefMI.getParent()) {
756 Inserter(InsertBB, std::next(InsertPt), UseMO);
775 unsigned CandidateLoadOpc;
777 case TargetOpcode::G_ANYEXT:
778 CandidateLoadOpc = TargetOpcode::G_LOAD;
780 case TargetOpcode::G_SEXT:
781 CandidateLoadOpc = TargetOpcode::G_SEXTLOAD;
783 case TargetOpcode::G_ZEXT:
784 CandidateLoadOpc = TargetOpcode::G_ZEXTLOAD;
789 return CandidateLoadOpc;
806 LLT LoadValueTy =
MRI.getType(LoadReg);
828 unsigned PreferredOpcode =
830 ? TargetOpcode::G_ANYEXT
832 Preferred = {
LLT(), PreferredOpcode,
nullptr};
833 for (
auto &
UseMI :
MRI.use_nodbg_instructions(LoadReg)) {
834 if (
UseMI.getOpcode() == TargetOpcode::G_SEXT ||
835 UseMI.getOpcode() == TargetOpcode::G_ZEXT ||
836 (
UseMI.getOpcode() == TargetOpcode::G_ANYEXT)) {
837 const auto &MMO = LoadMI->
getMMO();
845 LLT UseTy =
MRI.getType(
UseMI.getOperand(0).getReg());
847 if (
LI->getAction({CandidateLoadOpc, {UseTy, SrcTy}, {MMDesc}})
851 Preferred = ChoosePreferredUse(
MI, Preferred,
852 MRI.getType(
UseMI.getOperand(0).getReg()),
862 assert(Preferred.Ty != LoadValueTy &&
"Extending to same type?");
880 if (PreviouslyEmitted) {
887 Builder.setInsertPt(*InsertIntoBB, InsertBefore);
888 Register NewDstReg =
MRI.cloneVirtualRegister(
MI.getOperand(0).getReg());
890 EmittedInsns[InsertIntoBB] = NewMI;
896 MI.setDesc(
Builder.getTII().get(LoadOpc));
903 for (
auto *UseMO :
Uses) {
909 UseMI->getOpcode() == TargetOpcode::G_ANYEXT) {
912 const LLT UseDstTy =
MRI.getType(UseDstReg);
913 if (UseDstReg != ChosenDstReg) {
914 if (Preferred.
Ty == UseDstTy) {
951 InsertInsnsWithoutSideEffectsBeforeUse(
Builder,
MI, *UseMO,
966 InsertInsnsWithoutSideEffectsBeforeUse(
Builder,
MI, *UseMO, InsertTruncAt);
969 MI.getOperand(0).setReg(ChosenDstReg);
975 assert(
MI.getOpcode() == TargetOpcode::G_AND);
986 if (
MRI.getType(Dst).isVector())
994 APInt MaskVal = MaybeMask->Value;
1009 LLT RegTy =
MRI.getType(LoadReg);
1012 unsigned MaskSizeBits = MaskVal.
countr_one();
1015 !
MRI.hasOneNonDBGUse(LoadReg))
1020 if (MaskSizeBits > LoadSizeBits)
1039 else if (LoadSizeBits > MaskSizeBits || LoadSizeBits ==
RegSize)
1044 {TargetOpcode::G_ZEXTLOAD, {RegTy,
MRI.getType(PtrReg)}, {MemDesc}}))
1048 B.setInstrAndDebugLoc(*LoadMI);
1049 auto &MF =
B.getMF();
1051 auto *NewMMO = MF.getMachineMemOperand(MMO, PtrInfo, MemDesc.
MemoryTy);
1052 B.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, Dst, PtrReg, *NewMMO);
1062 "shouldn't consider debug uses");
1070 if (DefOrUse ==
MBB.end())
1072 return &*DefOrUse == &
DefMI;
1078 "shouldn't consider debug uses");
1081 else if (
DefMI.getParent() !=
UseMI.getParent())
1088 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1092 if (
MRI.getType(SrcReg).isVector())
1097 LoadUser = TruncSrc;
1099 uint64_t SizeInBits =
MI.getOperand(2).getImm();
1104 auto LoadSizeBits = LoadMI->getMemSizeInBits();
1106 MRI.getType(TruncSrc).getSizeInBits() < LoadSizeBits.getValue())
1108 if (LoadSizeBits == SizeInBits)
1115 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1116 Builder.buildCopy(
MI.getOperand(0).getReg(),
MI.getOperand(1).getReg());
1117 MI.eraseFromParent();
1121 MachineInstr &
MI, std::tuple<Register, unsigned> &MatchInfo)
const {
1122 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1125 LLT RegTy =
MRI.getType(DstReg);
1138 uint64_t ExtFrom =
MI.getOperand(2).getImm();
1140 if (MemBits > ExtFrom && !
MRI.hasOneNonDBGUse(SrcReg))
1146 unsigned NewSizeBits = std::min(ExtFrom, MemBits);
1149 if (NewSizeBits < 8)
1162 else if (MemBits > NewSizeBits || MemBits == RegTy.
getSizeInBits())
1167 {TargetOpcode::G_SEXTLOAD, {RegTy,
MRI.getType(PtrReg)}, {MMDesc}}))
1170 MatchInfo = std::make_tuple(SrcReg, NewSizeBits);
1175 MachineInstr &
MI, std::tuple<Register, unsigned> &MatchInfo)
const {
1176 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
1178 unsigned ScalarSizeBits;
1179 std::tie(LoadReg, ScalarSizeBits) = MatchInfo;
1188 auto &MMO = LoadDef->
getMMO();
1189 Builder.setInstrAndDebugLoc(*LoadDef);
1191 auto PtrInfo = MMO.getPointerInfo();
1192 auto *NewMMO = MF.getMachineMemOperand(&MMO, PtrInfo, ScalarSizeBits / 8);
1193 Builder.buildLoadInstr(TargetOpcode::G_SEXTLOAD,
MI.getOperand(0).getReg(),
1196 MI.eraseFromParent();
1207 auto *MF =
MI->getMF();
1214 AM.
BaseOffs = CstOff->getSExtValue();
1219 MF->getDataLayout(), AM,
1221 MF->getFunction().getContext()),
1222 MI->getMMO().getAddrSpace());
1227 case TargetOpcode::G_LOAD:
1228 return TargetOpcode::G_INDEXED_LOAD;
1229 case TargetOpcode::G_STORE:
1230 return TargetOpcode::G_INDEXED_STORE;
1231 case TargetOpcode::G_ZEXTLOAD:
1232 return TargetOpcode::G_INDEXED_ZEXTLOAD;
1233 case TargetOpcode::G_SEXTLOAD:
1234 return TargetOpcode::G_INDEXED_SEXTLOAD;
1240bool CombinerHelper::isIndexedLoadStoreLegal(
GLoadStore &LdSt)
const {
1250 if (IndexedOpc == TargetOpcode::G_INDEXED_STORE)
1251 OpTys = {PtrTy, Ty, Ty};
1253 OpTys = {Ty, PtrTy};
1255 LegalityQuery Q(IndexedOpc, OpTys, MemDescrs);
1261 cl::desc(
"Number of uses of a base pointer to check before it is no longer "
1262 "considered for post-indexing."));
1266 bool &RematOffset)
const {
1279 if (!isIndexedLoadStoreLegal(LdSt))
1290 unsigned NumUsesChecked = 0;
1303 if (StoredValDef == &
Use)
1306 Offset = PtrAdd->getOffsetReg();
1308 !TLI.isIndexingLegal(LdSt, PtrAdd->getBaseReg(),
Offset,
1316 RematOffset =
false;
1320 if (OffsetDef->
getOpcode() != TargetOpcode::G_CONSTANT)
1325 for (
auto &BasePtrUse :
MRI.use_nodbg_instructions(PtrAdd->getBaseReg())) {
1326 if (&BasePtrUse == PtrDef)
1332 if (BasePtrLdSt && BasePtrLdSt != &LdSt &&
1334 isIndexedLoadStoreLegal(*BasePtrLdSt))
1340 Register PtrAddDefReg = BasePtrUseDef->getReg(0);
1341 for (
auto &BaseUseUse :
MRI.use_nodbg_instructions(PtrAddDefReg)) {
1344 if (BaseUseUse.getParent() != LdSt.
getParent())
1356 Addr = PtrAdd->getReg(0);
1357 Base = PtrAdd->getBaseReg();
1372 MRI.hasOneNonDBGUse(Addr))
1379 if (!isIndexedLoadStoreLegal(LdSt))
1383 if (BaseDef->
getOpcode() == TargetOpcode::G_FRAME_INDEX)
1388 if (
Base == St->getValueReg())
1393 if (St->getValueReg() == Addr)
1398 for (
auto &AddrUse :
MRI.use_nodbg_instructions(Addr))
1399 if (AddrUse.getParent() != LdSt.
getParent())
1404 bool RealUse =
false;
1405 for (
auto &AddrUse :
MRI.use_nodbg_instructions(Addr)) {
1423 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT);
1433 assert(
MRI.getType(
MI.getOperand(0).getReg()) == VecEltTy);
1440 if (!LoadMI->isSimple())
1452 const unsigned MaxIter = 20;
1455 if (
II->isLoadFoldBarrier())
1457 if (Iter++ == MaxIter)
1473 int Elt = CVal->getZExtValue();
1486 Register VecPtr = LoadMI->getPointerReg();
1487 LLT PtrTy =
MRI.getType(VecPtr);
1495 {TargetOpcode::G_LOAD, {VecEltTy, PtrTy}, {MMDesc}}))
1518 B.buildLoad(Result, finalPtr, PtrInfo, Alignment);
1533 MatchInfo.
IsPre = findPreIndexCandidate(LdSt, MatchInfo.
Addr, MatchInfo.
Base,
1535 if (!MatchInfo.
IsPre &&
1536 !findPostIndexCandidate(LdSt, MatchInfo.
Addr, MatchInfo.
Base,
1546 unsigned Opcode =
MI.getOpcode();
1547 bool IsStore = Opcode == TargetOpcode::G_STORE;
1553 auto *OldCst =
MRI.getVRegDef(MatchInfo.
Offset);
1555 *OldCst->getOperand(1).getCImm());
1556 MatchInfo.
Offset = NewCst.getReg(0);
1559 auto MIB =
Builder.buildInstr(NewOpcode);
1561 MIB.addDef(MatchInfo.
Addr);
1562 MIB.addUse(
MI.getOperand(0).getReg());
1564 MIB.addDef(
MI.getOperand(0).getReg());
1565 MIB.addDef(MatchInfo.
Addr);
1568 MIB.addUse(MatchInfo.
Base);
1569 MIB.addUse(MatchInfo.
Offset);
1570 MIB.addImm(MatchInfo.
IsPre);
1571 MIB->cloneMemRefs(*
MI.getMF(),
MI);
1572 MI.eraseFromParent();
1580 unsigned Opcode =
MI.getOpcode();
1581 bool IsDiv, IsSigned;
1586 case TargetOpcode::G_SDIV:
1587 case TargetOpcode::G_UDIV: {
1589 IsSigned = Opcode == TargetOpcode::G_SDIV;
1592 case TargetOpcode::G_SREM:
1593 case TargetOpcode::G_UREM: {
1595 IsSigned = Opcode == TargetOpcode::G_SREM;
1601 unsigned DivOpcode, RemOpcode, DivremOpcode;
1603 DivOpcode = TargetOpcode::G_SDIV;
1604 RemOpcode = TargetOpcode::G_SREM;
1605 DivremOpcode = TargetOpcode::G_SDIVREM;
1607 DivOpcode = TargetOpcode::G_UDIV;
1608 RemOpcode = TargetOpcode::G_UREM;
1609 DivremOpcode = TargetOpcode::G_UDIVREM;
1627 for (
auto &
UseMI :
MRI.use_nodbg_instructions(Src1)) {
1628 if (
MI.getParent() ==
UseMI.getParent() &&
1629 ((IsDiv &&
UseMI.getOpcode() == RemOpcode) ||
1630 (!IsDiv &&
UseMI.getOpcode() == DivOpcode)) &&
1643 unsigned Opcode =
MI.getOpcode();
1644 assert(OtherMI &&
"OtherMI shouldn't be empty.");
1647 if (Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_UDIV) {
1648 DestDivReg =
MI.getOperand(0).getReg();
1652 DestRemReg =
MI.getOperand(0).getReg();
1656 Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_SREM;
1663 Builder.setInstrAndDebugLoc(*FirstInst);
1665 Builder.buildInstr(IsSigned ? TargetOpcode::G_SDIVREM
1666 : TargetOpcode::G_UDIVREM,
1667 {DestDivReg, DestRemReg},
1669 MI.eraseFromParent();
1675 assert(
MI.getOpcode() == TargetOpcode::G_BR);
1692 if (BrIt ==
MBB->begin())
1694 assert(std::next(BrIt) ==
MBB->end() &&
"expected G_BR to be a terminator");
1696 BrCond = &*std::prev(BrIt);
1697 if (BrCond->
getOpcode() != TargetOpcode::G_BRCOND)
1703 return BrCondTarget !=
MI.getOperand(0).getMBB() &&
1704 MBB->isLayoutSuccessor(BrCondTarget);
1710 Builder.setInstrAndDebugLoc(*BrCond);
1715 auto True =
Builder.buildConstant(
1721 MI.getOperand(0).setMBB(FallthroughBB);
1734 unsigned MaxLen)
const {
1735 auto &[Dst, Src, KnownLen, Alignment, DstAlignCanChange, MemOps] = MatchInfo;
1737 DstAlignCanChange, MemOps);
1742 auto &[Dst, Src, KnownLen, Alignment, DstAlignCanChange, MemOps] = MatchInfo;
1747 DstAlignCanChange, MemOps) ==
1749 assert(
Changed &&
"expected memcpy-family instruction to lower");
1754 unsigned MaxLen)
const {
1766 switch (
MI.getOpcode()) {
1769 case TargetOpcode::G_FNEG: {
1770 Result.changeSign();
1773 case TargetOpcode::G_FABS: {
1777 case TargetOpcode::G_FCEIL:
1780 case TargetOpcode::G_FFLOOR:
1783 case TargetOpcode::G_INTRINSIC_TRUNC:
1786 case TargetOpcode::G_INTRINSIC_ROUND:
1789 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
1792 case TargetOpcode::G_FRINT:
1793 case TargetOpcode::G_FNEARBYINT:
1797 case TargetOpcode::G_FPEXT:
1798 case TargetOpcode::G_FPTRUNC: {
1805 case TargetOpcode::G_FSQRT: {
1809 Result =
APFloat(sqrt(Result.convertToDouble()));
1812 case TargetOpcode::G_FLOG2: {
1832 Builder.buildFConstant(
MI.getOperand(0), *NewCst);
1833 MI.eraseFromParent();
1844 if (
MI.getOpcode() != TargetOpcode::G_PTR_ADD)
1867 Type *AccessTy =
nullptr;
1868 auto &MF = *
MI.getMF();
1869 for (
auto &
UseMI :
MRI.use_nodbg_instructions(
MI.getOperand(0).getReg())) {
1872 MF.getFunction().getContext());
1877 APInt CombinedImm = MaybeImmVal->Value + MaybeImm2Val->Value;
1882 AMOld.
BaseOffs = MaybeImmVal->Value.getSExtValue();
1884 unsigned AS =
MRI.getType(Add2).getAddressSpace();
1885 const auto &TLI = *MF.getSubtarget().getTargetLowering();
1886 if (TLI.isLegalAddressingMode(MF.getDataLayout(), AMOld, AccessTy, AS) &&
1887 !TLI.isLegalAddressingMode(MF.getDataLayout(), AMNew, AccessTy, AS))
1896 unsigned PtrAddFlags =
MI.getFlags();
1912 MatchInfo.
Flags = Flags;
1918 assert(
MI.getOpcode() == TargetOpcode::G_PTR_ADD &&
"Expected G_PTR_ADD");
1920 LLT OffsetTy =
MRI.getType(
MI.getOperand(2).getReg());
1924 MI.getOperand(1).setReg(MatchInfo.
Base);
1925 MI.getOperand(2).setReg(NewOffset.getReg(0));
1939 unsigned Opcode =
MI.getOpcode();
1940 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
1941 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_SSHLSAT ||
1942 Opcode == TargetOpcode::G_USHLSAT) &&
1943 "Expected G_SHL, G_ASHR, G_LSHR, G_SSHLSAT or G_USHLSAT");
1963 (MaybeImmVal->Value.getZExtValue() + MaybeImm2Val->Value).getZExtValue();
1968 if (Opcode == TargetOpcode::G_USHLSAT &&
1969 MatchInfo.
Imm >=
MRI.getType(Shl2).getScalarSizeInBits())
1977 unsigned Opcode =
MI.getOpcode();
1978 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
1979 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_SSHLSAT ||
1980 Opcode == TargetOpcode::G_USHLSAT) &&
1981 "Expected G_SHL, G_ASHR, G_LSHR, G_SSHLSAT or G_USHLSAT");
1983 LLT Ty =
MRI.getType(
MI.getOperand(1).getReg());
1984 unsigned const ScalarSizeInBits = Ty.getScalarSizeInBits();
1985 auto Imm = MatchInfo.
Imm;
1987 if (
Imm >= ScalarSizeInBits) {
1989 if (Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR) {
1990 Builder.buildConstant(
MI.getOperand(0), 0);
1991 MI.eraseFromParent();
1996 Imm = ScalarSizeInBits - 1;
1999 LLT ImmTy =
MRI.getType(
MI.getOperand(2).getReg());
2002 MI.getOperand(1).setReg(MatchInfo.
Reg);
2003 MI.getOperand(2).setReg(NewImm);
2019 unsigned ShiftOpcode =
MI.getOpcode();
2020 assert((ShiftOpcode == TargetOpcode::G_SHL ||
2021 ShiftOpcode == TargetOpcode::G_ASHR ||
2022 ShiftOpcode == TargetOpcode::G_LSHR ||
2023 ShiftOpcode == TargetOpcode::G_USHLSAT ||
2024 ShiftOpcode == TargetOpcode::G_SSHLSAT) &&
2025 "Expected G_SHL, G_ASHR, G_LSHR, G_USHLSAT and G_SSHLSAT");
2028 Register LogicDest =
MI.getOperand(1).getReg();
2029 if (!
MRI.hasOneNonDBGUse(LogicDest))
2035 unsigned LogicOpcode = LogicMI->
getOpcode();
2036 if (LogicOpcode != TargetOpcode::G_AND && LogicOpcode != TargetOpcode::G_OR &&
2037 LogicOpcode != TargetOpcode::G_XOR)
2041 const Register C1 =
MI.getOperand(2).getReg();
2043 if (!MaybeImmVal || MaybeImmVal->Value == 0)
2046 const uint64_t C1Val = MaybeImmVal->Value.getZExtValue();
2048 auto matchFirstShift = [&](
const MachineInstr *
MI, uint64_t &ShiftVal) {
2050 if (
MI->getOpcode() != ShiftOpcode ||
2051 !
MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()))
2060 ShiftVal = MaybeImmVal->Value.getSExtValue();
2074 if (matchFirstShift(LogicMIOp1, C0Val)) {
2076 MatchInfo.
Shift2 = LogicMIOp1;
2077 }
else if (matchFirstShift(LogicMIOp2, C0Val)) {
2079 MatchInfo.
Shift2 = LogicMIOp2;
2083 MatchInfo.
ValSum = C0Val + C1Val;
2086 if (MatchInfo.
ValSum >=
MRI.getType(LogicDest).getScalarSizeInBits())
2089 MatchInfo.
Logic = LogicMI;
2095 unsigned Opcode =
MI.getOpcode();
2096 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_ASHR ||
2097 Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_USHLSAT ||
2098 Opcode == TargetOpcode::G_SSHLSAT) &&
2099 "Expected G_SHL, G_ASHR, G_LSHR, G_USHLSAT and G_SSHLSAT");
2101 LLT ShlType =
MRI.getType(
MI.getOperand(2).getReg());
2102 LLT DestType =
MRI.getType(
MI.getOperand(0).getReg());
2108 Builder.buildInstr(Opcode, {DestType}, {Shift1Base, Const}).
getReg(0);
2117 Register Shift2Const =
MI.getOperand(2).getReg();
2119 .buildInstr(Opcode, {DestType},
2129 MI.eraseFromParent();
2134 assert(
MI.getOpcode() == TargetOpcode::G_SHL &&
"Expected G_SHL");
2159 LLT SrcTy =
MRI.getType(SrcReg);
2161 auto S1 =
B.buildShl(SrcTy,
X, ShiftReg);
2162 auto S2 =
B.buildShl(SrcTy, C1, ShiftReg);
2163 B.buildInstr(SrcOpc, {DstReg}, {
S1, S2});
2171 assert(
MI.getOpcode() == TargetOpcode::G_LSHR &&
"Expected a G_LSHR");
2175 unsigned OpSizeInBits =
MRI.getType(N0).getScalarSizeInBits();
2190 LLT InnerShiftTy =
MRI.getType(InnerShift);
2192 if ((N1C + N001C).ult(InnerShiftSize)) {
2198 if ((N001C + OpSizeInBits) == InnerShiftSize)
2200 if (
MRI.hasOneUse(N0) &&
MRI.hasOneUse(InnerShift)) {
2201 MatchInfo.
Mask =
true;
2211 assert(
MI.getOpcode() == TargetOpcode::G_LSHR &&
"Expected a G_LSHR");
2218 if (MatchInfo.
Mask ==
true) {
2226 Builder.buildTrunc(Dst, Shift);
2227 MI.eraseFromParent();
2231 unsigned &ShiftVal)
const {
2232 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
"Expected a G_MUL");
2238 ShiftVal = MaybeImmVal->Value.exactLogBase2();
2239 return (
static_cast<int32_t
>(ShiftVal) != -1);
2243 unsigned &ShiftVal)
const {
2244 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
"Expected a G_MUL");
2246 LLT ShiftTy =
MRI.getType(
MI.getOperand(0).getReg());
2249 MI.setDesc(MIB.
getTII().
get(TargetOpcode::G_SHL));
2250 MI.getOperand(2).setReg(ShiftCst.getReg(0));
2271 auto NegCst =
B.buildConstant(Ty, -
Imm);
2273 MI.setDesc(
B.getTII().get(TargetOpcode::G_ADD));
2274 MI.getOperand(2).setReg(NegCst.getReg(0));
2276 if (
Imm.isMinSignedValue())
2286 assert(
MI.getOpcode() == TargetOpcode::G_SHL &&
VT);
2300 if (!MaybeShiftAmtVal)
2304 LLT SrcTy =
MRI.getType(ExtSrc);
2314 int64_t ShiftAmt = MaybeShiftAmtVal->getSExtValue();
2315 MatchData.
Reg = ExtSrc;
2316 MatchData.
Imm = ShiftAmt;
2318 unsigned MinLeadingZeros =
VT->getKnownZeroes(ExtSrc).countl_one();
2319 unsigned SrcTySize =
MRI.getType(ExtSrc).getScalarSizeInBits();
2320 return MinLeadingZeros >= ShiftAmt && ShiftAmt < SrcTySize;
2326 int64_t ShiftAmtVal = MatchData.
Imm;
2328 LLT ExtSrcTy =
MRI.getType(ExtSrcReg);
2329 auto ShiftAmt =
Builder.buildConstant(ExtSrcTy, ShiftAmtVal);
2331 Builder.buildShl(ExtSrcTy, ExtSrcReg, ShiftAmt,
MI.getFlags());
2332 Builder.buildZExt(
MI.getOperand(0), NarrowShift);
2333 MI.eraseFromParent();
2340 for (
unsigned I = 0;
I <
Merge.getNumSources(); ++
I)
2344 if (!Unmerge || Unmerge->getNumDefs() !=
Merge.getNumSources())
2347 for (
unsigned I = 0;
I < MergedValues.
size(); ++
I)
2348 if (MergedValues[
I] != Unmerge->getReg(
I))
2351 MatchInfo = Unmerge->getSourceReg();
2365 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2366 "Expected an unmerge");
2375 LLT SrcMergeTy =
MRI.getType(SrcInstr->getSourceReg(0));
2376 LLT Dst0Ty =
MRI.getType(Unmerge.getReg(0));
2378 if (SrcMergeTy != Dst0Ty && !SameSize)
2382 for (
unsigned Idx = 0; Idx < SrcInstr->getNumSources(); ++Idx)
2383 Operands.push_back(SrcInstr->getSourceReg(Idx));
2389 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2390 "Expected an unmerge");
2392 "Not enough operands to replace all defs");
2393 unsigned NumElems =
MI.getNumOperands() - 1;
2396 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
2397 bool CanReuseInputDirectly = DstTy == SrcTy;
2398 for (
unsigned Idx = 0; Idx < NumElems; ++Idx) {
2399 Register DstReg =
MI.getOperand(Idx).getReg();
2404 const auto &DstCB =
MRI.getRegClassOrRegBank(DstReg);
2405 if (!DstCB.isNull() && DstCB !=
MRI.getRegClassOrRegBank(SrcReg)) {
2406 SrcReg =
Builder.buildCopy(
MRI.getType(SrcReg), SrcReg).getReg(0);
2407 MRI.setRegClassOrRegBank(SrcReg, DstCB);
2410 if (CanReuseInputDirectly)
2413 Builder.buildCast(DstReg, SrcReg);
2415 MI.eraseFromParent();
2420 unsigned SrcIdx =
MI.getNumOperands() - 1;
2421 Register SrcReg =
MI.getOperand(SrcIdx).getReg();
2427 LLT Dst0Ty =
MRI.getType(
MI.getOperand(0).getReg());
2430 for (
unsigned Idx = 0; Idx != SrcIdx; ++Idx) {
2432 Val = Val.
lshr(ShiftAmt);
2440 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2441 "Expected an unmerge");
2443 "Not enough operands to replace all defs");
2444 unsigned NumElems =
MI.getNumOperands() - 1;
2445 for (
unsigned Idx = 0; Idx < NumElems; ++Idx) {
2446 Register DstReg =
MI.getOperand(Idx).getReg();
2447 Builder.buildConstant(DstReg, Csts[Idx]);
2450 MI.eraseFromParent();
2456 unsigned SrcIdx =
MI.getNumOperands() - 1;
2457 Register SrcReg =
MI.getOperand(SrcIdx).getReg();
2459 unsigned NumElems =
MI.getNumOperands() - 1;
2460 for (
unsigned Idx = 0; Idx < NumElems; ++Idx) {
2461 Register DstReg =
MI.getOperand(Idx).getReg();
2462 B.buildUndef(DstReg);
2470 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2471 "Expected an unmerge");
2472 if (!
MRI.getType(
MI.getOperand(0).getReg()).isScalar() ||
2473 !
MRI.getType(
MI.getOperand(
MI.getNumDefs()).getReg()).isScalar())
2476 for (
unsigned Idx = 1, EndIdx =
MI.getNumDefs(); Idx != EndIdx; ++Idx) {
2477 if (!
MRI.use_nodbg_empty(
MI.getOperand(Idx).getReg()))
2485 Register SrcReg =
MI.getOperand(
MI.getNumDefs()).getReg();
2486 Register Dst0Reg =
MI.getOperand(0).getReg();
2487 Builder.buildTrunc(Dst0Reg, SrcReg);
2488 MI.eraseFromParent();
2492 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2493 "Expected an unmerge");
2494 Register Dst0Reg =
MI.getOperand(0).getReg();
2495 LLT Dst0Ty =
MRI.getType(Dst0Reg);
2501 Register SrcReg =
MI.getOperand(
MI.getNumDefs()).getReg();
2502 LLT SrcTy =
MRI.getType(SrcReg);
2503 if (SrcTy.isVector())
2513 LLT ZExtSrcTy =
MRI.getType(ZExtSrcReg);
2518 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES &&
2519 "Expected an unmerge");
2521 Register Dst0Reg =
MI.getOperand(0).getReg();
2526 LLT Dst0Ty =
MRI.getType(Dst0Reg);
2527 LLT ZExtSrcTy =
MRI.getType(ZExtSrcReg);
2530 Builder.buildZExt(Dst0Reg, ZExtSrcReg);
2533 "ZExt src doesn't fit in destination");
2538 for (
unsigned Idx = 1, EndIdx =
MI.getNumDefs(); Idx != EndIdx; ++Idx) {
2540 ZeroReg =
Builder.buildConstant(Dst0Ty, 0).getReg(0);
2543 MI.eraseFromParent();
2547 unsigned TargetShiftSize,
2548 unsigned &ShiftVal)
const {
2549 assert((
MI.getOpcode() == TargetOpcode::G_SHL ||
2550 MI.getOpcode() == TargetOpcode::G_LSHR ||
2551 MI.getOpcode() == TargetOpcode::G_ASHR) &&
"Expected a shift");
2553 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
2558 unsigned Size = Ty.getSizeInBits();
2559 if (
Size <= TargetShiftSize)
2567 ShiftVal = MaybeImmVal->Value.getSExtValue();
2568 return ShiftVal >=
Size / 2 && ShiftVal <
Size;
2575 LLT Ty =
MRI.getType(SrcReg);
2576 unsigned Size = Ty.getSizeInBits();
2577 unsigned HalfSize =
Size / 2;
2578 assert(ShiftVal >= HalfSize);
2582 auto Unmerge =
Builder.buildUnmerge(HalfTy, SrcReg);
2583 unsigned NarrowShiftAmt = ShiftVal - HalfSize;
2585 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
2586 Register Narrowed = Unmerge.getReg(1);
2593 if (NarrowShiftAmt != 0) {
2594 Narrowed =
Builder.buildLShr(HalfTy, Narrowed,
2595 Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
2598 auto Zero =
Builder.buildConstant(HalfTy, 0);
2599 Builder.buildMergeLikeInstr(DstReg, {Narrowed, Zero});
2600 }
else if (
MI.getOpcode() == TargetOpcode::G_SHL) {
2601 Register Narrowed = Unmerge.getReg(0);
2606 if (NarrowShiftAmt != 0) {
2607 Narrowed =
Builder.buildShl(HalfTy, Narrowed,
2608 Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
2611 auto Zero =
Builder.buildConstant(HalfTy, 0);
2612 Builder.buildMergeLikeInstr(DstReg, {Zero, Narrowed});
2614 assert(
MI.getOpcode() == TargetOpcode::G_ASHR);
2616 HalfTy, Unmerge.getReg(1),
2617 Builder.buildConstant(HalfTy, HalfSize - 1));
2619 if (ShiftVal == HalfSize) {
2622 Builder.buildMergeLikeInstr(DstReg, {Unmerge.getReg(1),
Hi});
2623 }
else if (ShiftVal ==
Size - 1) {
2631 HalfTy, Unmerge.getReg(1),
2632 Builder.buildConstant(HalfTy, ShiftVal - HalfSize));
2640 MI.eraseFromParent();
2656 assert(
MI.getOpcode() == TargetOpcode::G_INTTOPTR &&
"Expected a G_INTTOPTR");
2658 LLT DstTy =
MRI.getType(DstReg);
2666 assert(
MI.getOpcode() == TargetOpcode::G_INTTOPTR &&
"Expected a G_INTTOPTR");
2668 Builder.buildCopy(DstReg, Reg);
2669 MI.eraseFromParent();
2674 assert(
MI.getOpcode() == TargetOpcode::G_PTRTOINT &&
"Expected a G_PTRTOINT");
2676 Builder.buildZExtOrTrunc(DstReg, Reg);
2677 MI.eraseFromParent();
2682 assert(
MI.getOpcode() == TargetOpcode::G_ADD);
2685 LLT IntTy =
MRI.getType(LHS);
2689 PtrReg.second =
false;
2690 for (
Register SrcReg : {LHS, RHS}) {
2694 LLT PtrTy =
MRI.getType(PtrReg.first);
2699 PtrReg.second =
true;
2711 const bool DoCommute = PtrReg.second;
2716 LLT PtrTy =
MRI.getType(LHS);
2718 auto PtrAdd =
Builder.buildPtrAdd(PtrTy, LHS, RHS);
2719 Builder.buildPtrToInt(Dst, PtrAdd);
2720 MI.eraseFromParent();
2724 APInt &NewCst)
const {
2726 Register LHS = PtrAdd.getBaseReg();
2727 Register RHS = PtrAdd.getOffsetReg();
2733 auto DstTy =
MRI.getType(PtrAdd.getReg(0));
2736 NewCst += RHSCst->
sextOrTrunc(DstTy.getSizeInBits());
2745 APInt &NewCst)
const {
2749 Builder.buildConstant(Dst, NewCst);
2750 PtrAdd.eraseFromParent();
2755 assert(
MI.getOpcode() == TargetOpcode::G_ANYEXT &&
"Expected a G_ANYEXT");
2760 SrcReg = OriginalSrcReg;
2761 LLT DstTy =
MRI.getType(DstReg);
2769 assert(
MI.getOpcode() == TargetOpcode::G_ZEXT &&
"Expected a G_ZEXT");
2772 LLT DstTy =
MRI.getType(DstReg);
2777 unsigned SrcSize =
MRI.getType(SrcReg).getScalarSizeInBits();
2778 return VT->getKnownBits(Reg).countMinLeadingZeros() >= DstSize - SrcSize;
2788 if (ShiftSize > 32 && TruncSize < 32)
2801 MachineInstr &
MI, std::pair<MachineInstr *, LLT> &MatchInfo)
const {
2802 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC &&
"Expected a G_TRUNC");
2806 if (!
MRI.hasOneNonDBGUse(SrcReg))
2809 LLT SrcTy =
MRI.getType(SrcReg);
2810 LLT DstTy =
MRI.getType(DstReg);
2819 case TargetOpcode::G_SHL: {
2828 case TargetOpcode::G_LSHR:
2829 case TargetOpcode::G_ASHR: {
2835 for (
auto &
User :
MRI.use_instructions(DstReg))
2836 if (
User.getOpcode() == TargetOpcode::G_STORE)
2840 if (NewShiftTy == SrcTy)
2854 {NewShiftTy, TL.getPreferredShiftAmountTy(NewShiftTy)}}))
2857 MatchInfo = std::make_pair(SrcMI, NewShiftTy);
2862 MachineInstr &
MI, std::pair<MachineInstr *, LLT> &MatchInfo)
const {
2864 LLT NewShiftTy = MatchInfo.second;
2867 LLT DstTy =
MRI.getType(Dst);
2871 ShiftSrc =
Builder.buildTrunc(NewShiftTy, ShiftSrc).getReg(0);
2874 LLT PrefShiftTy = TL.getPreferredShiftAmountTy(NewShiftTy);
2875 if (
MRI.getType(ShiftAmt) != PrefShiftTy)
2876 ShiftAmt =
Builder.buildZExtOrTrunc(PrefShiftTy, ShiftAmt).getReg(0);
2880 .buildInstr(ShiftMI->
getOpcode(), {NewShiftTy}, {ShiftSrc, ShiftAmt})
2883 if (NewShiftTy == DstTy)
2886 Builder.buildTrunc(Dst, NewShift);
2893 return MO.isReg() &&
2894 getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
2900 return !MO.isReg() ||
2901 getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
2906 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
2908 return all_of(Mask, [](
int Elt) {
return Elt < 0; });
2912 assert(
MI.getOpcode() == TargetOpcode::G_STORE);
2913 return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
MI.getOperand(0).getReg(),
2918 assert(
MI.getOpcode() == TargetOpcode::G_SELECT);
2919 return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF,
MI.getOperand(1).getReg(),
2925 assert((
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT ||
2926 MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT) &&
2927 "Expected an insert/extract element op");
2928 LLT VecTy =
MRI.getType(
MI.getOperand(1).getReg());
2933 MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
2941 unsigned &OpIdx)
const {
2946 OpIdx = Cst->isZero() ? 3 : 2;
2991 if (I1->mayLoadOrStore() && !I1->isDereferenceableInvariantLoad())
3018 return MO.isReg() && MO.getReg().isPhysical();
3028 return I1->isIdenticalTo(*I2);
3036 if (
Builder.getTII().produceSameValue(*I1, *I2, &
MRI)) {
3043 return I1->findRegisterDefOperandIdx(InstAndDef1->Reg,
nullptr) ==
3054 return MaybeCst && MaybeCst->getBitWidth() <= 64 &&
3055 MaybeCst->getSExtValue() ==
C;
3062 std::optional<FPValueAndVReg> MaybeCst;
3066 return MaybeCst->Value.isExactlyValue(
C);
3070 unsigned OpIdx)
const {
3071 assert(
MI.getNumExplicitDefs() == 1 &&
"Expected one explicit def?");
3073 Register Replacement =
MI.getOperand(OpIdx).getReg();
3076 MI.eraseFromParent();
3081 assert(
MI.getNumExplicitDefs() == 1 &&
"Expected one explicit def?");
3085 MI.eraseFromParent();
3089 unsigned ConstIdx)
const {
3090 Register ConstReg =
MI.getOperand(ConstIdx).getReg();
3091 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
3103 assert((
MI.getOpcode() == TargetOpcode::G_FSHL ||
3104 MI.getOpcode() == TargetOpcode::G_FSHR) &&
3105 "This is not a funnel shift operation");
3107 Register ConstReg =
MI.getOperand(3).getReg();
3108 LLT ConstTy =
MRI.getType(ConstReg);
3109 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
3112 assert((VRegAndVal) &&
"Value is not a constant");
3115 APInt NewConst = VRegAndVal->Value.
urem(
3120 MI.getOpcode(), {MI.getOperand(0)},
3121 {MI.getOperand(1), MI.getOperand(2), NewConstInstr.getReg(0)});
3123 MI.eraseFromParent();
3127 assert(
MI.getOpcode() == TargetOpcode::G_SELECT);
3141 unsigned OpIdx)
const {
3143 return MO.
isReg() &&
3154 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3156 MI.eraseFromParent();
3161 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3163 MI.eraseFromParent();
3167 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3169 MI.eraseFromParent();
3174 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3176 MI.eraseFromParent();
3180 assert(
MI.getNumDefs() == 1 &&
"Expected only one def?");
3182 MI.eraseFromParent();
3186 MachineInstr &
MI, std::tuple<Register, Register> &MatchInfo)
const {
3189 Register &NewLHS = std::get<0>(MatchInfo);
3190 Register &NewRHS = std::get<1>(MatchInfo);
3198 NewLHS = MaybeNewLHS;
3202 return CheckFold(LHS, RHS) || CheckFold(RHS, LHS);
3207 assert(
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT &&
3210 LLT DstTy =
MRI.getType(DstReg);
3219 if (
MRI.hasOneUse(DstReg) &&
MRI.use_instr_begin(DstReg)->getOpcode() ==
3220 TargetOpcode::G_INSERT_VECTOR_ELT)
3226 MatchInfo.
resize(NumElts);
3230 if (IntImm >= NumElts || IntImm < 0)
3232 if (!MatchInfo[IntImm])
3233 MatchInfo[IntImm] = TmpReg;
3237 if (CurrInst->
getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
3239 if (TmpInst->
getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
3248 return TmpInst->
getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
3255 auto GetUndef = [&]() {
3258 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
3266 Builder.buildBuildVector(
MI.getOperand(0).getReg(), MatchInfo);
3267 MI.eraseFromParent();
3271 MachineInstr &
MI, std::tuple<Register, Register> &MatchInfo)
const {
3273 std::tie(SubLHS, SubRHS) = MatchInfo;
3274 Builder.buildSub(
MI.getOperand(0).getReg(), SubLHS, SubRHS);
3275 MI.eraseFromParent();
3288 unsigned InnerOpc = InnerDef->
getOpcode();
3289 if (InnerOpc != TargetOpcode::G_ADD && InnerOpc != TargetOpcode::G_SUB)
3313 if (!TryMatch(InnerLHS, InnerRHS) &&
3314 !(InnerOpc == TargetOpcode::G_ADD && TryMatch(InnerRHS, InnerLHS)))
3318 unsigned FlippedOpc = (InnerOpc == TargetOpcode::G_ADD) ? TargetOpcode::G_SUB
3319 : TargetOpcode::G_ADD;
3322 MatchInfo = [=](MachineIRBuilder &
Builder) {
3323 auto NewInner =
Builder.buildInstr(FlippedOpc, {Ty}, {
B,
C});
3324 auto NewNot =
Builder.buildNot(Ty, NewInner);
3325 Builder.buildInstr(RootOpc, {Dst}, {
A, NewNot});
3337 unsigned RootOpc =
MI.getOpcode();
3339 LLT Ty =
MRI.getType(Dst);
3344 return matchBinopWithNegInner(LHS, RHS, RootOpc, Dst, Ty, MatchInfo) ||
3345 matchBinopWithNegInner(RHS, LHS, RootOpc, Dst, Ty, MatchInfo);
3356 unsigned LogicOpcode =
MI.getOpcode();
3357 assert(LogicOpcode == TargetOpcode::G_AND ||
3358 LogicOpcode == TargetOpcode::G_OR ||
3359 LogicOpcode == TargetOpcode::G_XOR);
3366 if (!
MRI.hasOneNonDBGUse(LHSReg) || !
MRI.hasOneNonDBGUse(RHSReg))
3372 if (!LeftHandInst || !RightHandInst)
3374 unsigned HandOpcode = LeftHandInst->
getOpcode();
3375 if (HandOpcode != RightHandInst->
getOpcode())
3389 if (!XTy.
isValid() || XTy != YTy)
3394 switch (HandOpcode) {
3397 case TargetOpcode::G_ANYEXT:
3398 case TargetOpcode::G_SEXT:
3399 case TargetOpcode::G_ZEXT: {
3403 case TargetOpcode::G_TRUNC: {
3408 LLT DstTy =
MRI.getType(Dst);
3417 case TargetOpcode::G_AND:
3418 case TargetOpcode::G_ASHR:
3419 case TargetOpcode::G_LSHR:
3420 case TargetOpcode::G_SHL: {
3425 ExtraHandOpSrcReg = ZOp.
getReg();
3436 auto NewLogicDst =
MRI.createGenericVirtualRegister(XTy);
3447 if (ExtraHandOpSrcReg.
isValid())
3459 "Expected at least one instr to build?");
3461 assert(InstrToBuild.Opcode &&
"Expected a valid opcode?");
3462 assert(InstrToBuild.OperandFns.size() &&
"Expected at least one operand?");
3464 for (
auto &OperandFn : InstrToBuild.OperandFns)
3467 MI.eraseFromParent();
3471 MachineInstr &
MI, std::tuple<Register, int64_t> &MatchInfo)
const {
3472 assert(
MI.getOpcode() == TargetOpcode::G_ASHR);
3473 int64_t ShlCst, AshrCst;
3479 if (ShlCst != AshrCst)
3482 {TargetOpcode::G_SEXT_INREG,
3485 {
MRI.getType(Src).getScalarSizeInBits() - ShlCst}}))
3487 MatchInfo = std::make_tuple(Src, ShlCst);
3492 MachineInstr &
MI, std::tuple<Register, int64_t> &MatchInfo)
const {
3493 assert(
MI.getOpcode() == TargetOpcode::G_ASHR);
3496 std::tie(Src, ShiftAmt) = MatchInfo;
3497 unsigned Size =
MRI.getType(Src).getScalarSizeInBits();
3498 Builder.buildSExtInReg(
MI.getOperand(0).getReg(), Src,
Size - ShiftAmt);
3499 MI.eraseFromParent();
3506 assert(
MI.getOpcode() == TargetOpcode::G_AND);
3509 LLT Ty =
MRI.getType(Dst);
3521 B.buildAnd(Dst, R,
B.buildConstant(Ty, C1 & C2));
3524 auto Zero =
B.buildConstant(Ty, 0);
3547 assert(
MI.getOpcode() == TargetOpcode::G_AND);
3571 (LHSBits.
Zero | RHSBits.
One).isAllOnes()) {
3578 (LHSBits.
One | RHSBits.
Zero).isAllOnes()) {
3595 assert(
MI.getOpcode() == TargetOpcode::G_OR);
3613 (LHSBits.
One | RHSBits.
Zero).isAllOnes()) {
3620 (LHSBits.
Zero | RHSBits.
One).isAllOnes()) {
3631 unsigned ExtBits =
MI.getOperand(2).getImm();
3632 unsigned TypeSize =
MRI.getType(Src).getScalarSizeInBits();
3633 return VT->computeNumSignBits(Src) >= (
TypeSize - ExtBits + 1);
3637 int64_t Cst,
bool IsVector,
bool IsFP) {
3639 return (ScalarSizeBits == 1 && Cst == -1) ||
3661 unsigned BuildUseCount = BV.getNumSources();
3662 if (BuildUseCount % 2 != 0)
3665 unsigned NumUnmerge = BuildUseCount / 2;
3671 if (!Unmerge || Unmerge->getNumDefs() != NumUnmerge)
3674 UnmergeSrc = Unmerge->getSourceReg();
3676 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
3677 LLT UnmergeSrcTy =
MRI.getType(UnmergeSrc);
3684 !
isLegal({TargetOpcode::G_CONCAT_VECTORS, {DstTy, UnmergeSrcTy}}))
3689 for (
unsigned I = 0;
I < NumUnmerge; ++
I) {
3690 auto MaybeUnmergeReg = BV.getSourceReg(
I);
3693 if (!LoopUnmerge || LoopUnmerge != Unmerge)
3696 if (LoopUnmerge->getOperand(
I).getReg() != MaybeUnmergeReg)
3701 if (Unmerge->getNumDefs() != NumUnmerge)
3705 for (
unsigned I = NumUnmerge;
I < BuildUseCount; ++
I) {
3708 if (
Undef->getOpcode() != TargetOpcode::G_IMPLICIT_DEF)
3719 assert(UnmergeSrc &&
"Expected there to be one matching G_UNMERGE_VALUES");
3720 B.setInstrAndDebugLoc(
MI);
3722 Register UndefVec =
B.buildUndef(
MRI.getType(UnmergeSrc)).getReg(0);
3723 B.buildConcatVectors(
MI.getOperand(0), {UnmergeSrc, UndefVec});
3725 MI.eraseFromParent();
3747 unsigned NumOperands =
BuildMI->getNumSources();
3757 for (
I = 0;
I < NumOperands; ++
I) {
3769 UnmergeMI != UnmergeSrcMI)
3780 for (;
I < NumOperands; ++
I) {
3787 LLT UnmergeSrcTy =
MRI.getType(MatchInfo);
3794 LLT UnmergeDstEltTy =
MRI.getType(UnmergeDstReg);
3795 if (UnmergeSrcEltTy != UnmergeDstEltTy)
3803 !
isLegal({TargetOpcode::G_CONCAT_VECTORS, {MidTy, UnmergeSrcTy}}))
3806 if (!
isLegal({TargetOpcode::G_TRUNC, {DstTy, MidTy}}))
3818 LLT DstTy =
MRI.getType(DstReg);
3819 LLT UnmergeSrcTy =
MRI.getType(MatchInfo);
3824 if (DstTyNumElt / UnmergeSrcTyNumElt == 1) {
3829 for (
unsigned I = 1;
I < DstTyNumElt / UnmergeSrcTyNumElt; ++
I)
3833 MidReg =
Builder.buildConcatVectors(MidTy, ConcatRegs).getReg(0);
3836 Builder.buildTrunc(DstReg, MidReg);
3837 MI.eraseFromParent();
3842 assert(
MI.getOpcode() == TargetOpcode::G_XOR);
3843 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
3844 const auto &TLI = *
Builder.getMF().getSubtarget().getTargetLowering();
3852 if (!
MRI.hasOneNonDBGUse(XorSrc))
3862 for (
unsigned I = 0;
I < RegsToNegate.
size(); ++
I) {
3864 if (!
MRI.hasOneNonDBGUse(Reg))
3869 switch (Def->getOpcode()) {
3874 case TargetOpcode::G_ICMP:
3880 case TargetOpcode::G_FCMP:
3886 case TargetOpcode::G_AND:
3887 case TargetOpcode::G_OR:
3893 RegsToNegate.
push_back(Def->getOperand(1).getReg());
3894 RegsToNegate.
push_back(Def->getOperand(2).getReg());
3902 if (Ty.isVector()) {
3906 if (!
isConstValidTrue(TLI, Ty.getScalarSizeInBits(), SplatCst,
true, IsFP))
3920 for (
Register Reg : RegsToNegate) {
3925 switch (Def->getOpcode()) {
3928 case TargetOpcode::G_ICMP:
3929 case TargetOpcode::G_FCMP: {
3936 case TargetOpcode::G_AND:
3937 Def->setDesc(
Builder.getTII().get(TargetOpcode::G_OR));
3939 case TargetOpcode::G_OR:
3940 Def->setDesc(
Builder.getTII().get(TargetOpcode::G_AND));
3947 MI.eraseFromParent();
3951 MachineInstr &
MI, std::pair<Register, Register> &MatchInfo)
const {
3953 assert(
MI.getOpcode() == TargetOpcode::G_XOR);
3957 Register SharedReg =
MI.getOperand(2).getReg();
3971 if (!
MRI.hasOneNonDBGUse(AndReg))
3978 return Y == SharedReg;
3982 MachineInstr &
MI, std::pair<Register, Register> &MatchInfo)
const {
3985 std::tie(
X,
Y) = MatchInfo;
3988 MI.setDesc(
Builder.getTII().get(TargetOpcode::G_AND));
3989 MI.getOperand(1).setReg(Not->getOperand(0).getReg());
3990 MI.getOperand(2).setReg(
Y);
3996 Register DstReg = PtrAdd.getReg(0);
3997 LLT Ty =
MRI.getType(DstReg);
4000 if (
DL.isNonIntegralAddressSpace(Ty.getScalarType().getAddressSpace()))
4003 if (Ty.isPointer()) {
4005 return ConstVal && *ConstVal == 0;
4008 assert(Ty.isVector() &&
"Expecting a vector type");
4017 Builder.buildIntToPtr(PtrAdd.getReg(0), PtrAdd.getOffsetReg());
4018 PtrAdd.eraseFromParent();
4025 Register Pow2Src1 =
MI.getOperand(2).getReg();
4026 LLT Ty =
MRI.getType(DstReg);
4029 auto NegOne =
Builder.buildConstant(Ty, -1);
4030 auto Add =
Builder.buildAdd(Ty, Pow2Src1, NegOne);
4032 MI.eraseFromParent();
4036 unsigned &SelectOpNo)
const {
4048 !
MRI.hasOneNonDBGUse(LHS)) {
4049 OtherOperandReg = LHS;
4053 !
MRI.hasOneNonDBGUse(RHS))
4071 unsigned BinOpcode =
MI.getOpcode();
4076 bool CanFoldNonConst =
4077 (BinOpcode == TargetOpcode::G_AND || BinOpcode == TargetOpcode::G_OR) &&
4082 if (CanFoldNonConst)
4107 LLT Ty =
MRI.getType(Dst);
4108 unsigned BinOpcode =
MI.getOpcode();
4115 if (SelectOperand == 1) {
4119 FoldTrue =
Builder.buildInstr(BinOpcode, {Ty}, {SelectTrue, RHS}).
getReg(0);
4121 Builder.buildInstr(BinOpcode, {Ty}, {SelectFalse, RHS}).
getReg(0);
4123 FoldTrue =
Builder.buildInstr(BinOpcode, {Ty}, {LHS, SelectTrue}).
getReg(0);
4125 Builder.buildInstr(BinOpcode, {Ty}, {LHS, SelectFalse}).
getReg(0);
4128 Builder.buildSelect(Dst, SelectCond, FoldTrue, FoldFalse,
MI.getFlags());
4129 MI.eraseFromParent();
4132std::optional<SmallVector<Register, 8>>
4133CombinerHelper::findCandidatesForLoadOrCombine(
const MachineInstr *Root)
const {
4134 assert(Root->
getOpcode() == TargetOpcode::G_OR &&
"Expected G_OR only!");
4163 const unsigned MaxIter =
4165 for (
unsigned Iter = 0; Iter < MaxIter; ++Iter) {
4174 return std::nullopt;
4190 if (RegsToVisit.
empty() || RegsToVisit.
size() % 2 != 0)
4191 return std::nullopt;
4203static std::optional<std::pair<GZExtLoad *, int64_t>>
4207 "Expected Reg to only have one non-debug use?");
4216 if (Shift % MemSizeInBits != 0)
4217 return std::nullopt;
4222 return std::nullopt;
4224 if (!
Load->isUnordered() ||
Load->getMemSizeInBits() != MemSizeInBits)
4225 return std::nullopt;
4227 return std::make_pair(
Load, Shift / MemSizeInBits);
4230std::optional<std::tuple<GZExtLoad *, int64_t, GZExtLoad *>>
4231CombinerHelper::findLoadOffsetsForLoadOrCombine(
4234 const unsigned MemSizeInBits)
const {
4237 SmallSetVector<const MachineInstr *, 8> Loads;
4243 GZExtLoad *LowestIdxLoad =
nullptr;
4246 SmallSet<int64_t, 8> SeenIdx;
4250 MachineBasicBlock *
MBB =
nullptr;
4251 const MachineMemOperand *MMO =
nullptr;
4254 GZExtLoad *EarliestLoad =
nullptr;
4257 GZExtLoad *LatestLoad =
nullptr;
4266 for (
auto Reg : RegsToVisit) {
4271 return std::nullopt;
4274 std::tie(
Load, DstPos) = *LoadAndPos;
4278 MachineBasicBlock *LoadMBB =
Load->getParent();
4282 return std::nullopt;
4285 auto &LoadMMO =
Load->getMMO();
4289 return std::nullopt;
4296 LoadPtr =
Load->getOperand(1).getReg();
4301 if (!SeenIdx.
insert(Idx).second)
4302 return std::nullopt;
4309 if (BasePtr != LoadPtr)
4310 return std::nullopt;
4312 if (Idx < LowestIdx) {
4314 LowestIdxLoad =
Load;
4321 if (!MemOffset2Idx.
try_emplace(DstPos, Idx).second)
4322 return std::nullopt;
4331 EarliestLoad =
Load;
4339 "Expected to find a load for each register?");
4340 assert(EarliestLoad != LatestLoad && EarliestLoad &&
4341 LatestLoad &&
"Expected at least two loads?");
4350 const unsigned MaxIter = 20;
4356 if (
MI.isLoadFoldBarrier())
4357 return std::nullopt;
4358 if (Iter++ == MaxIter)
4359 return std::nullopt;
4362 return std::make_tuple(LowestIdxLoad, LowestIdx, LatestLoad);
4368 assert(
MI.getOpcode() == TargetOpcode::G_OR);
4381 LLT Ty =
MRI.getType(Dst);
4387 const unsigned WideMemSizeInBits = Ty.getSizeInBits();
4388 if (WideMemSizeInBits < 16 || WideMemSizeInBits % 8 != 0)
4392 auto RegsToVisit = findCandidatesForLoadOrCombine(&
MI);
4399 const unsigned NarrowMemSizeInBits = WideMemSizeInBits / RegsToVisit->size();
4400 if (NarrowMemSizeInBits % 8 != 0)
4413 auto MaybeLoadInfo = findLoadOffsetsForLoadOrCombine(
4414 MemOffset2Idx, *RegsToVisit, NarrowMemSizeInBits);
4417 std::tie(LowestIdxLoad, LowestIdx, LatestLoad) = *MaybeLoadInfo;
4424 std::optional<bool> IsBigEndian =
isBigEndian(MemOffset2Idx, LowestIdx);
4427 bool NeedsBSwap = IsBigEndianTarget != *IsBigEndian;
4439 const unsigned NumLoadsInTy = WideMemSizeInBits / NarrowMemSizeInBits;
4440 const unsigned ZeroByteOffset =
4444 auto ZeroOffsetIdx = MemOffset2Idx.
find(ZeroByteOffset);
4445 if (ZeroOffsetIdx == MemOffset2Idx.
end() ||
4446 ZeroOffsetIdx->second != LowestIdx)
4456 {TargetOpcode::G_LOAD, {Ty,
MRI.getType(Ptr)}, {MMDesc}}))
4470 MIB.setInstrAndDebugLoc(*LatestLoad);
4471 Register LoadDst = NeedsBSwap ?
MRI.cloneVirtualRegister(Dst) : Dst;
4472 MIB.buildLoad(LoadDst, Ptr, *NewMMO);
4474 MIB.buildBSwap(Dst, LoadDst);
4486 if (
MRI.getType(DstReg).isVector())
4490 if (!
MRI.hasOneNonDBGUse(DstReg))
4492 ExtMI = &*
MRI.use_instr_nodbg_begin(DstReg);
4494 case TargetOpcode::G_ANYEXT:
4496 case TargetOpcode::G_ZEXT:
4497 case TargetOpcode::G_SEXT:
4504 if (
Builder.getTII().isExtendLikelyToBeFolded(*ExtMI,
MRI))
4511 for (
unsigned I = 0;
I <
PHI.getNumIncomingValues(); ++
I) {
4513 switch (
DefMI->getOpcode()) {
4514 case TargetOpcode::G_LOAD:
4515 case TargetOpcode::G_TRUNC:
4516 case TargetOpcode::G_SEXT:
4517 case TargetOpcode::G_ZEXT:
4518 case TargetOpcode::G_ANYEXT:
4519 case TargetOpcode::G_CONSTANT:
4523 if (InSrcs.
size() > 2)
4537 LLT ExtTy =
MRI.getType(DstReg);
4544 for (
unsigned I = 0;
I <
PHI.getNumIncomingValues(); ++
I) {
4545 auto SrcReg =
PHI.getIncomingValue(
I);
4549 if (!SrcMIs.
insert(SrcMI))
4555 if (InsertPt !=
MBB->end() && InsertPt->isPHI())
4556 InsertPt =
MBB->getFirstNonPHI();
4561 OldToNewSrcMap[SrcMI] = NewExt;
4566 auto NewPhi =
Builder.buildInstrNoInsert(TargetOpcode::G_PHI);
4567 NewPhi.addDef(DstReg);
4570 NewPhi.addMBB(MO.getMBB());
4573 auto *NewSrc = OldToNewSrcMap[
MRI.getVRegDef(MO.getReg())];
4574 NewPhi.addUse(NewSrc->getOperand(0).getReg());
4582 assert(
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT);
4586 LLT SrcTy =
MRI.getType(SrcVec);
4587 if (SrcTy.isScalableVector())
4591 if (!Cst || Cst->Value.getZExtValue() >= SrcTy.getNumElements())
4594 unsigned VecIdx = Cst->Value.getZExtValue();
4606 if (SrcVecMI->
getOpcode() != TargetOpcode::G_BUILD_VECTOR &&
4607 SrcVecMI->
getOpcode() != TargetOpcode::G_BUILD_VECTOR_TRUNC)
4611 if (!
MRI.hasOneNonDBGUse(SrcVec) &&
4623 LLT ScalarTy =
MRI.getType(Reg);
4625 LLT DstTy =
MRI.getType(DstReg);
4627 if (ScalarTy != DstTy) {
4629 Builder.buildTrunc(DstReg, Reg);
4630 MI.eraseFromParent();
4638 SmallVectorImpl<std::pair<Register, MachineInstr *>> &SrcDstPairs)
const {
4639 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
4657 LLT DstTy =
MRI.getType(DstReg);
4662 if (
II.getOpcode() != TargetOpcode::G_EXTRACT_VECTOR_ELT)
4667 unsigned Idx = Cst->getZExtValue();
4670 ExtractedElts.
set(Idx);
4671 SrcDstPairs.emplace_back(
4672 std::make_pair(
MI.getOperand(Idx + 1).getReg(), &
II));
4675 return ExtractedElts.
all();
4680 SmallVectorImpl<std::pair<Register, MachineInstr *>> &SrcDstPairs)
const {
4681 assert(
MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
4682 for (
auto &Pair : SrcDstPairs) {
4683 auto *ExtMI = Pair.second;
4685 ExtMI->eraseFromParent();
4687 MI.eraseFromParent();
4694 MI.eraseFromParent();
4704 bool AllowScalarConstants,
4706 assert(
MI.getOpcode() == TargetOpcode::G_OR);
4709 LLT Ty =
MRI.getType(Dst);
4710 unsigned BitWidth = Ty.getScalarSizeInBits();
4712 Register ShlSrc, ShlAmt, LShrSrc, LShrAmt, Amt;
4713 unsigned FshOpc = 0;
4724 int64_t CstShlAmt = 0, CstLShrAmt;
4727 CstShlAmt + CstLShrAmt ==
BitWidth) {
4728 FshOpc = TargetOpcode::G_FSHR;
4734 FshOpc = TargetOpcode::G_FSHL;
4739 FshOpc = TargetOpcode::G_FSHR;
4744 LLT AmtTy =
MRI.getType(Amt);
4746 (!AllowScalarConstants || CstShlAmt == 0 || !Ty.isScalar()))
4750 B.buildInstr(FshOpc, {Dst}, {ShlSrc, LShrSrc, Amt});
4757 unsigned Opc =
MI.getOpcode();
4758 assert(
Opc == TargetOpcode::G_FSHL ||
Opc == TargetOpcode::G_FSHR);
4763 unsigned RotateOpc =
4764 Opc == TargetOpcode::G_FSHL ? TargetOpcode::G_ROTL : TargetOpcode::G_ROTR;
4769 unsigned Opc =
MI.getOpcode();
4770 assert(
Opc == TargetOpcode::G_FSHL ||
Opc == TargetOpcode::G_FSHR);
4771 bool IsFSHL =
Opc == TargetOpcode::G_FSHL;
4773 MI.setDesc(
Builder.getTII().get(IsFSHL ? TargetOpcode::G_ROTL
4774 : TargetOpcode::G_ROTR));
4775 MI.removeOperand(2);
4781 assert(
MI.getOpcode() == TargetOpcode::G_ROTL ||
4782 MI.getOpcode() == TargetOpcode::G_ROTR);
4784 MRI.getType(
MI.getOperand(0).getReg()).getScalarSizeInBits();
4786 bool OutOfRange =
false;
4787 auto MatchOutOfRange = [Bitsize, &OutOfRange](
const Constant *
C) {
4789 OutOfRange |= CI->getValue().uge(Bitsize);
4796 assert(
MI.getOpcode() == TargetOpcode::G_ROTL ||
4797 MI.getOpcode() == TargetOpcode::G_ROTR);
4799 MRI.getType(
MI.getOperand(0).getReg()).getScalarSizeInBits();
4801 LLT AmtTy =
MRI.getType(Amt);
4802 auto Bits =
Builder.buildConstant(AmtTy, Bitsize);
4803 Amt =
Builder.buildURem(AmtTy,
MI.getOperand(2).getReg(), Bits).getReg(0);
4805 MI.getOperand(2).setReg(Amt);
4810 int64_t &MatchInfo)
const {
4811 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
4822 auto KnownRHS =
VT->getKnownBits(
MI.getOperand(3).getReg());
4823 if (KnownRHS.isUnknown())
4826 std::optional<bool> KnownVal;
4827 if (KnownRHS.isZero()) {
4837 auto KnownLHS =
VT->getKnownBits(
MI.getOperand(2).getReg());
4847 MRI.getType(
MI.getOperand(0).getReg()).isVector(),
4856 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
4872 LLT DstTy =
MRI.getType(Dst);
4880 auto KnownLHS =
VT->getKnownBits(LHS);
4881 if (KnownLHS.getMinValue() != 0 || KnownLHS.getMaxValue() != 1)
4884 LLT LHSTy =
MRI.getType(LHS);
4887 unsigned Op = TargetOpcode::COPY;
4888 if (DstSize != LHSSize)
4889 Op = DstSize < LHSSize ? TargetOpcode::G_TRUNC : TargetOpcode::G_ZEXT;
4900 assert(
MI.getOpcode() == TargetOpcode::G_AND);
4904 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
4910 int64_t AndMaskBits;
4918 if (AndMaskBits & OrMaskBits)
4924 if (
MI.getOperand(1).getReg() == AndMaskReg)
4925 MI.getOperand(2).setReg(AndMaskReg);
4926 MI.getOperand(1).setReg(Src);
4936 assert(
MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
4939 LLT Ty =
MRI.getType(Src);
4941 if (!
LI || !
LI->isLegalOrCustom({TargetOpcode::G_SBFX, {Ty, ExtractTy}}))
4943 int64_t Width =
MI.getOperand(2).getImm();
4951 if (ShiftImm < 0 || ShiftImm + Width > Ty.getScalarSizeInBits())
4955 auto Cst1 =
B.buildConstant(ExtractTy, ShiftImm);
4956 auto Cst2 =
B.buildConstant(ExtractTy, Width);
4957 B.buildSbfx(Dst, ShiftSrc, Cst1, Cst2);
4967 LLT Ty =
MRI.getType(Dst);
4971 if (
LI && !
LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
4974 int64_t AndImm, LSBImm;
4976 const unsigned Size = Ty.getScalarSizeInBits();
4983 auto MaybeMask =
static_cast<uint64_t
>(AndImm);
4984 if (MaybeMask & (MaybeMask + 1))
4988 if (
static_cast<uint64_t
>(LSBImm) >=
Size)
4993 auto WidthCst =
B.buildConstant(ExtractTy, Width);
4994 auto LSBCst =
B.buildConstant(ExtractTy, LSBImm);
4995 B.buildInstr(TargetOpcode::G_UBFX, {Dst}, {ShiftSrc, LSBCst, WidthCst});
5003 const unsigned Opcode =
MI.getOpcode();
5004 assert(Opcode == TargetOpcode::G_ASHR || Opcode == TargetOpcode::G_LSHR);
5006 const Register Dst =
MI.getOperand(0).getReg();
5008 const unsigned ExtrOpcode = Opcode == TargetOpcode::G_ASHR
5009 ? TargetOpcode::G_SBFX
5010 : TargetOpcode::G_UBFX;
5013 LLT Ty =
MRI.getType(Dst);
5015 if (!
LI || !
LI->isLegalOrCustom({ExtrOpcode, {Ty, ExtractTy}}))
5021 const unsigned Size = Ty.getScalarSizeInBits();
5031 if (ShlAmt < 0 || ShlAmt > ShrAmt || ShrAmt >=
Size)
5035 if (Opcode == TargetOpcode::G_ASHR && ShlAmt == ShrAmt)
5039 const int64_t Pos = ShrAmt - ShlAmt;
5040 const int64_t Width =
Size - ShrAmt;
5043 auto WidthCst =
B.buildConstant(ExtractTy, Width);
5044 auto PosCst =
B.buildConstant(ExtractTy, Pos);
5045 B.buildInstr(ExtrOpcode, {Dst}, {ShlSrc, PosCst, WidthCst});
5053 const unsigned Opcode =
MI.getOpcode();
5054 assert(Opcode == TargetOpcode::G_LSHR || Opcode == TargetOpcode::G_ASHR);
5056 const Register Dst =
MI.getOperand(0).getReg();
5057 LLT Ty =
MRI.getType(Dst);
5059 if (
LI && !
LI->isLegalOrCustom({TargetOpcode::G_UBFX, {Ty, ExtractTy}}))
5072 const unsigned Size = Ty.getScalarSizeInBits();
5073 if (ShrAmt < 0 || ShrAmt >=
Size)
5077 if (0 == (SMask >> ShrAmt)) {
5079 B.buildConstant(Dst, 0);
5092 const int64_t Pos = ShrAmt;
5097 if (Opcode == TargetOpcode::G_ASHR && Width + ShrAmt ==
Size)
5101 auto WidthCst =
B.buildConstant(ExtractTy, Width);
5102 auto PosCst =
B.buildConstant(ExtractTy, Pos);
5103 B.buildInstr(TargetOpcode::G_UBFX, {Dst}, {AndSrc, PosCst, WidthCst});
5108bool CombinerHelper::reassociationCanBreakAddressingModePattern(
5112 Register Src1Reg = PtrAdd.getBaseReg();
5117 Register Src2Reg = PtrAdd.getOffsetReg();
5119 if (
MRI.hasOneNonDBGUse(Src1Reg))
5129 const APInt &C1APIntVal = *C1;
5130 const APInt &C2APIntVal = *C2;
5131 const int64_t CombinedValue = (C1APIntVal + C2APIntVal).getSExtValue();
5133 for (
auto &
UseMI :
MRI.use_nodbg_instructions(PtrAdd.getReg(0))) {
5136 MachineInstr *ConvUseMI = &
UseMI;
5137 unsigned ConvUseOpc = ConvUseMI->
getOpcode();
5138 while (ConvUseOpc == TargetOpcode::G_INTTOPTR ||
5139 ConvUseOpc == TargetOpcode::G_PTRTOINT) {
5141 if (!
MRI.hasOneNonDBGUse(DefReg))
5143 ConvUseMI = &*
MRI.use_instr_nodbg_begin(DefReg);
5152 TargetLoweringBase::AddrMode AM;
5155 unsigned AS =
MRI.getType(LdStMI->getPointerReg()).getAddressSpace();
5157 PtrAdd.getMF()->getFunction().getContext());
5158 const auto &TLI = *PtrAdd.getMF()->getSubtarget().getTargetLowering();
5159 if (!TLI.isLegalAddressingMode(PtrAdd.getMF()->getDataLayout(), AM,
5165 if (!TLI.isLegalAddressingMode(PtrAdd.getMF()->getDataLayout(), AM,
5177 Register Src1Reg =
MI.getOperand(1).getReg();
5178 if (RHS->getOpcode() != TargetOpcode::G_ADD)
5190 unsigned PtrAddFlags =
MI.getFlags();
5191 unsigned AddFlags = RHS->getFlags();
5204 LLT PtrTy =
MRI.getType(
MI.getOperand(0).getReg());
5207 Builder.buildPtrAdd(PtrTy, Src1Reg, RHS->getOperand(1).getReg(), Flags);
5209 MI.getOperand(1).setReg(NewBase.getReg(0));
5210 MI.getOperand(2).setReg(RHS->getOperand(2).getReg());
5214 return !reassociationCanBreakAddressingModePattern(
MI);
5224 std::optional<ValueAndVReg> LHSCstOff;
5234 unsigned PtrAddFlags =
MI.getFlags();
5235 unsigned LHSPtrAddFlags = LHSPtrAdd->getFlags();
5237 bool IsNoUSWrap = IsNoUWrap && (PtrAddFlags & LHSPtrAddFlags &
5239 bool IsInBounds = IsNoUWrap && (PtrAddFlags & LHSPtrAddFlags &
5253 LHSPtrAdd->moveBefore(&
MI);
5256 auto NewCst =
B.buildConstant(
MRI.getType(RHSReg), LHSCstOff->Value);
5258 MI.getOperand(2).setReg(NewCst.getReg(0));
5261 Observer.changingInstr(*LHSPtrAdd);
5262 LHSPtrAdd->getOperand(2).setReg(RHSReg);
5263 LHSPtrAdd->setFlags(Flags);
5266 return !reassociationCanBreakAddressingModePattern(
MI);
5277 Register Src2Reg =
MI.getOperand(2).getReg();
5278 Register LHSSrc1 = LHSPtrAdd->getBaseReg();
5279 Register LHSSrc2 = LHSPtrAdd->getOffsetReg();
5292 unsigned PtrAddFlags =
MI.getFlags();
5293 unsigned LHSPtrAddFlags = LHSPtrAdd->getFlags();
5306 auto NewCst =
B.buildConstant(
MRI.getType(Src2Reg), *C1 + *C2);
5308 MI.getOperand(1).setReg(LHSSrc1);
5309 MI.getOperand(2).setReg(NewCst.getReg(0));
5313 return !reassociationCanBreakAddressingModePattern(
MI);
5353 LLT OpRHSTy =
MRI.getType(OpRHS);
5370 auto NewCst =
B.buildInstr(
Opc, {OpRHSTy}, {OpLHSRHS, OpRHS});
5371 B.buildInstr(
Opc, {DstReg}, {OpLHSLHS, NewCst});
5379 auto NewLHSLHS =
B.buildInstr(
Opc, {OpRHSTy}, {OpLHSLHS, OpRHS});
5380 B.buildInstr(
Opc, {DstReg}, {NewLHSLHS, OpLHSRHS});
5393 unsigned Opc =
MI.getOpcode();
5406 APInt &MatchInfo)
const {
5407 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
5411 MatchInfo = *MaybeCst;
5422 MI.getOperand(1).getReg(),
MRI);
5427 if (Csts.size() == 1)
5428 B.buildConstant(Dst, Csts[0]);
5430 B.buildBuildVectorConstant(Dst, Csts);
5436 APInt &MatchInfo)
const {
5442 MatchInfo = *MaybeCst;
5454 ConstantFP::get(
MI.getMF()->getFunction().getContext(), *MaybeCst);
5460 assert(
MI.getOpcode() == TargetOpcode::G_FMA ||
5461 MI.getOpcode() == TargetOpcode::G_FMAD);
5462 auto [
_, Op1, Op2, Op3] =
MI.getFirst4Regs();
5479 MatchInfo = ConstantFP::get(
MI.getMF()->getFunction().getContext(), Op1F);
5502 assert(
MI.getOpcode() == TargetOpcode::G_AND);
5506 LLT WideTy =
MRI.getType(Dst);
5510 if (!WideTy.
isScalar() || !
MRI.hasOneNonDBGUse(AndLHS))
5526 case TargetOpcode::G_ADD:
5527 case TargetOpcode::G_SUB:
5528 case TargetOpcode::G_MUL:
5529 case TargetOpcode::G_AND:
5530 case TargetOpcode::G_OR:
5531 case TargetOpcode::G_XOR:
5539 auto Mask = Cst->Value;
5544 unsigned NarrowWidth = Mask.countr_one();
5550 auto &MF = *
MI.getMF();
5553 if (!TLI.isTruncateFree(WideTy, NarrowTy, Ctx) ||
5554 !TLI.isZExtFree(NarrowTy, WideTy, Ctx))
5562 auto NarrowLHS =
Builder.buildTrunc(NarrowTy, BinOpLHS);
5563 auto NarrowRHS =
Builder.buildTrunc(NarrowTy, BinOpRHS);
5565 Builder.buildInstr(LHSOpc, {NarrowTy}, {NarrowLHS, NarrowRHS});
5566 auto Ext =
Builder.buildZExt(WideTy, NarrowBinOp);
5568 MI.getOperand(1).setReg(Ext.getReg(0));
5576 unsigned Opc =
MI.getOpcode();
5577 assert(
Opc == TargetOpcode::G_UMULO ||
Opc == TargetOpcode::G_SMULO);
5584 unsigned NewOpc =
Opc == TargetOpcode::G_UMULO ? TargetOpcode::G_UADDO
5585 : TargetOpcode::G_SADDO;
5586 MI.setDesc(
Builder.getTII().get(NewOpc));
5587 MI.getOperand(3).setReg(
MI.getOperand(2).getReg());
5596 assert(
MI.getOpcode() == TargetOpcode::G_UMULO ||
5597 MI.getOpcode() == TargetOpcode::G_SMULO);
5606 B.buildConstant(Dst, 0);
5607 B.buildConstant(Carry, 0);
5616 assert(
MI.getOpcode() == TargetOpcode::G_UADDE ||
5617 MI.getOpcode() == TargetOpcode::G_SADDE ||
5618 MI.getOpcode() == TargetOpcode::G_USUBE ||
5619 MI.getOpcode() == TargetOpcode::G_SSUBE);
5624 switch (
MI.getOpcode()) {
5625 case TargetOpcode::G_UADDE:
5626 NewOpcode = TargetOpcode::G_UADDO;
5628 case TargetOpcode::G_SADDE:
5629 NewOpcode = TargetOpcode::G_SADDO;
5631 case TargetOpcode::G_USUBE:
5632 NewOpcode = TargetOpcode::G_USUBO;
5634 case TargetOpcode::G_SSUBE:
5635 NewOpcode = TargetOpcode::G_SSUBO;
5639 MI.setDesc(
B.getTII().get(NewOpcode));
5640 MI.removeOperand(4);
5648 assert(
MI.getOpcode() == TargetOpcode::G_SUB);
5681 auto Zero =
B.buildConstant(
MRI.getType(Dst), 0);
5682 B.buildSub(Dst, Zero, ReplaceReg);
5691 unsigned Opcode =
MI.getOpcode();
5692 assert(Opcode == TargetOpcode::G_UDIV || Opcode == TargetOpcode::G_UREM);
5694 Register Dst = UDivorRem.getReg(0);
5695 Register LHS = UDivorRem.getReg(1);
5696 Register RHS = UDivorRem.getReg(2);
5697 LLT Ty =
MRI.getType(Dst);
5705 bool UseSRL =
false;
5710 auto BuildExactUDIVPattern = [&](
const Constant *
C) {
5712 if (IsSplat && !Factors.
empty()) {
5719 APInt Divisor = CI->getValue();
5728 Shifts.
push_back(MIB.buildConstant(ScalarShiftAmtTy, Shift).getReg(0));
5729 Factors.
push_back(MIB.buildConstant(ScalarTy, Factor).getReg(0));
5739 if (Ty.isVector()) {
5740 Shift = MIB.buildBuildVector(ShiftAmtTy, Shifts).getReg(0);
5741 Factor = MIB.buildBuildVector(Ty, Factors).getReg(0);
5744 Factor = Factors[0];
5752 return MIB.buildMul(Ty, Res, Factor);
5755 unsigned KnownLeadingZeros =
5756 VT ?
VT->getKnownBits(LHS).countMinLeadingZeros() : 0;
5758 bool UseNPQ =
false;
5760 auto BuildUDIVPattern = [&](
const Constant *
C) {
5762 const APInt &Divisor = CI->getValue();
5764 bool SelNPQ =
false;
5766 unsigned PreShift = 0, PostShift = 0;
5771 if (!Divisor.
isOne()) {
5777 Divisor, std::min(KnownLeadingZeros, Divisor.
countl_zero()));
5779 Magic = std::move(magics.
Magic);
5782 "We shouldn't generate an undefined shift!");
5784 "We shouldn't generate an undefined shift!");
5788 SelNPQ = magics.
IsAdd;
5792 MIB.buildConstant(ScalarShiftAmtTy, PreShift).getReg(0));
5793 MagicFactors.
push_back(MIB.buildConstant(ScalarTy, Magic).getReg(0));
5795 MIB.buildConstant(ScalarTy,
5800 MIB.buildConstant(ScalarShiftAmtTy, PostShift).getReg(0));
5808 assert(Matched &&
"Expected unary predicate match to succeed");
5810 Register PreShift, PostShift, MagicFactor, NPQFactor;
5813 PreShift = MIB.buildBuildVector(ShiftAmtTy, PreShifts).getReg(0);
5814 MagicFactor = MIB.buildBuildVector(Ty, MagicFactors).getReg(0);
5815 NPQFactor = MIB.buildBuildVector(Ty, NPQFactors).getReg(0);
5816 PostShift = MIB.buildBuildVector(ShiftAmtTy, PostShifts).getReg(0);
5819 "Non-build_vector operation should have been a scalar");
5820 PreShift = PreShifts[0];
5821 MagicFactor = MagicFactors[0];
5822 PostShift = PostShifts[0];
5826 Q = MIB.buildLShr(Ty, Q, PreShift).getReg(0);
5829 Q = MIB.buildUMulH(Ty, Q, MagicFactor).getReg(0);
5832 Register NPQ = MIB.buildSub(Ty, LHS, Q).getReg(0);
5837 NPQ = MIB.buildUMulH(Ty, NPQ, NPQFactor).getReg(0);
5839 NPQ = MIB.buildLShr(Ty, NPQ, MIB.buildConstant(ShiftAmtTy, 1)).getReg(0);
5841 Q = MIB.buildAdd(Ty, NPQ, Q).getReg(0);
5844 Q = MIB.buildLShr(Ty, Q, PostShift).getReg(0);
5845 auto One = MIB.buildConstant(Ty, 1);
5846 auto IsOne = MIB.buildICmp(
5850 auto ret = MIB.buildSelect(Ty, IsOne, LHS, Q);
5852 if (Opcode == TargetOpcode::G_UREM) {
5853 auto Prod = MIB.buildMul(Ty, ret, RHS);
5854 return MIB.buildSub(Ty, LHS, Prod);
5860 unsigned Opcode =
MI.getOpcode();
5861 assert(Opcode == TargetOpcode::G_UDIV || Opcode == TargetOpcode::G_UREM);
5864 LLT DstTy =
MRI.getType(Dst);
5866 auto &MF = *
MI.getMF();
5867 AttributeList Attr = MF.getFunction().getAttributes();
5876 if (MF.getFunction().hasMinSize())
5879 if (Opcode == TargetOpcode::G_UDIV &&
5882 MRI, RHS, [](
const Constant *
C) {
return C && !
C->isNullValue(); });
5897 {TargetOpcode::G_ICMP,
5901 if (Opcode == TargetOpcode::G_UREM &&
5907 MRI, RHS, [](
const Constant *
C) {
return C && !
C->isNullValue(); });
5916 unsigned Opcode =
MI.getOpcode();
5917 assert(Opcode == TargetOpcode::G_SDIV || Opcode == TargetOpcode::G_SREM);
5920 LLT DstTy =
MRI.getType(Dst);
5924 auto &MF = *
MI.getMF();
5925 AttributeList Attr = MF.getFunction().getAttributes();
5934 if (MF.getFunction().hasMinSize())
5938 if (Opcode == TargetOpcode::G_SDIV &&
5941 MRI, RHS, [](
const Constant *
C) {
return C && !
C->isNullValue(); });
5953 if (!
isLegal({TargetOpcode::G_SMULH, {DstTy}}) &&
5956 if (Opcode == TargetOpcode::G_SREM &&
5962 MRI, RHS, [](
const Constant *
C) {
return C && !
C->isNullValue(); });
5971 unsigned Opcode =
MI.getOpcode();
5972 assert(
MI.getOpcode() == TargetOpcode::G_SDIV ||
5973 Opcode == TargetOpcode::G_SREM);
5975 Register Dst = SDivorRem.getReg(0);
5976 Register LHS = SDivorRem.getReg(1);
5977 Register RHS = SDivorRem.getReg(2);
5978 LLT Ty =
MRI.getType(Dst);
5985 bool UseSRA =
false;
5991 auto BuildExactSDIVPattern = [&](
const Constant *
C) {
5993 if (IsSplat && !ExactFactors.
empty()) {
5995 ExactFactors.
push_back(ExactFactors[0]);
6000 APInt Divisor = CI->getValue();
6010 ExactShifts.
push_back(MIB.buildConstant(ScalarShiftAmtTy, Shift).getReg(0));
6011 ExactFactors.
push_back(MIB.buildConstant(ScalarTy, Factor).getReg(0));
6019 assert(Matched &&
"Expected unary predicate match to succeed");
6022 if (Ty.isVector()) {
6023 Shift = MIB.buildBuildVector(ShiftAmtTy, ExactShifts).getReg(0);
6024 Factor = MIB.buildBuildVector(Ty, ExactFactors).getReg(0);
6026 Shift = ExactShifts[0];
6027 Factor = ExactFactors[0];
6035 return MIB.buildMul(Ty, Res, Factor);
6040 auto BuildSDIVPattern = [&](
const Constant *
C) {
6042 const APInt &Divisor = CI->getValue();
6046 int NumeratorFactor = 0;
6057 NumeratorFactor = 1;
6060 NumeratorFactor = -1;
6063 MagicFactors.
push_back(MIB.buildConstant(ScalarTy, Magics.
Magic).getReg(0));
6064 Factors.
push_back(MIB.buildConstant(ScalarTy, NumeratorFactor).getReg(0));
6066 MIB.buildConstant(ScalarShiftAmtTy, Magics.
ShiftAmount).getReg(0));
6067 ShiftMasks.
push_back(MIB.buildConstant(ScalarTy, ShiftMask).getReg(0));
6075 assert(Matched &&
"Expected unary predicate match to succeed");
6077 Register MagicFactor, Factor, Shift, ShiftMask;
6080 MagicFactor = MIB.buildBuildVector(Ty, MagicFactors).getReg(0);
6081 Factor = MIB.buildBuildVector(Ty, Factors).getReg(0);
6082 Shift = MIB.buildBuildVector(ShiftAmtTy, Shifts).getReg(0);
6083 ShiftMask = MIB.buildBuildVector(Ty, ShiftMasks).getReg(0);
6086 "Non-build_vector operation should have been a scalar");
6087 MagicFactor = MagicFactors[0];
6088 Factor = Factors[0];
6090 ShiftMask = ShiftMasks[0];
6094 Q = MIB.buildSMulH(Ty, LHS, MagicFactor).getReg(0);
6097 Factor = MIB.buildMul(Ty, LHS, Factor).getReg(0);
6098 Q = MIB.buildAdd(Ty, Q, Factor).getReg(0);
6101 Q = MIB.buildAShr(Ty, Q, Shift).getReg(0);
6104 auto SignShift = MIB.buildConstant(ShiftAmtTy, EltBits - 1);
6105 auto T = MIB.buildLShr(Ty, Q, SignShift);
6106 T = MIB.buildAnd(Ty,
T, ShiftMask);
6107 auto ret = MIB.buildAdd(Ty, Q,
T);
6109 if (Opcode == TargetOpcode::G_SREM) {
6110 auto Prod = MIB.buildMul(Ty, ret, RHS);
6111 return MIB.buildSub(Ty, LHS, Prod);
6117 assert((
MI.getOpcode() == TargetOpcode::G_SDIV ||
6118 MI.getOpcode() == TargetOpcode::G_UDIV) &&
6119 "Expected SDIV or UDIV");
6122 auto MatchPow2 = [&](
const Constant *
C) {
6124 return CI && (CI->getValue().isPowerOf2() ||
6125 (IsSigned && CI->getValue().isNegatedPowerOf2()));
6131 assert(
MI.getOpcode() == TargetOpcode::G_SDIV &&
"Expected SDIV");
6136 LLT Ty =
MRI.getType(Dst);
6156 unsigned BitWidth = Ty.getScalarSizeInBits();
6157 auto Zero =
Builder.buildConstant(Ty, 0);
6160 auto C1 =
Builder.buildCTTZ(ShiftAmtTy, RHS);
6161 auto Inexact =
Builder.buildSub(ShiftAmtTy, Bits, C1);
6163 auto Sign =
Builder.buildAShr(
6167 auto LSrl =
Builder.buildLShr(Ty, Sign, Inexact);
6173 auto One =
Builder.buildConstant(Ty, 1);
6174 auto MinusOne =
Builder.buildConstant(Ty, -1);
6178 auto IsOneOrMinusOne =
Builder.buildOr(CCVT, IsOne, IsMinusOne);
6179 AShr =
Builder.buildSelect(Ty, IsOneOrMinusOne, LHS, AShr);
6183 auto Neg =
Builder.buildNeg(Ty, AShr);
6185 Builder.buildSelect(
MI.getOperand(0).getReg(), IsNeg, Neg, AShr);
6186 MI.eraseFromParent();
6190 assert(
MI.getOpcode() == TargetOpcode::G_UDIV &&
"Expected UDIV");
6195 LLT Ty =
MRI.getType(Dst);
6198 auto C1 =
Builder.buildCTTZ(ShiftAmtTy, RHS);
6199 Builder.buildLShr(
MI.getOperand(0).getReg(), LHS, C1);
6200 MI.eraseFromParent();
6204 assert(
MI.getOpcode() == TargetOpcode::G_SREM &&
"Expected SREM");
6209 LLT Ty =
MRI.getType(Dst);
6228 unsigned BitWidth = Ty.getScalarSizeInBits();
6229 auto AbsRHS =
Builder.buildAbs(Ty, RHS);
6230 auto Mask =
Builder.buildSub(Ty, AbsRHS,
Builder.buildConstant(Ty, 1));
6232 auto Sign =
Builder.buildAShr(Ty, LHS, BWMinusOne);
6233 auto Bias =
Builder.buildAnd(Ty, Sign, Mask);
6234 auto Biased =
Builder.buildAdd(Ty, LHS, Bias);
6237 MI.eraseFromParent();
6241 assert(
MI.getOpcode() == TargetOpcode::G_UMULH);
6244 LLT Ty =
MRI.getType(Dst);
6245 LLT RHSTy =
MRI.getType(RHS);
6247 auto MatchPow2ExceptOne = [&](
const Constant *
C) {
6249 return CI->getValue().isPowerOf2() && !CI->getValue().isOne();
6264 LLT Ty =
MRI.getType(Dst);
6270 Builder.buildSub(Ty,
Builder.buildConstant(Ty, NumEltBits), LogBase2);
6271 auto Trunc =
Builder.buildZExtOrTrunc(ShiftAmtTy, ShiftAmt);
6272 Builder.buildLShr(Dst, LHS, Trunc);
6273 MI.eraseFromParent();
6280 LLT DstTy =
MRI.getType(Dst);
6281 LLT SrcTy =
MRI.getType(Src);
6283 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6284 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
6287 {TargetOpcode::G_TRUNC_SSAT_S, {DstTy, SrcTy}}))
6316 Builder.buildTruncSSatS(Dst, MatchInfo);
6317 MI.eraseFromParent();
6324 LLT DstTy =
MRI.getType(Dst);
6325 LLT SrcTy =
MRI.getType(Src);
6327 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6328 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
6331 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6349 Builder.buildTruncSSatU(Dst, MatchInfo);
6350 MI.eraseFromParent();
6357 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6358 LLT SrcTy =
MRI.getType(Val);
6360 unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
6361 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
6364 {TargetOpcode::G_TRUNC_SSAT_U, {DstTy, SrcTy}}))
6373 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6382 unsigned Opc =
MI.getOpcode();
6383 assert(
Opc == TargetOpcode::G_FADD ||
Opc == TargetOpcode::G_FSUB ||
6384 Opc == TargetOpcode::G_FMUL ||
Opc == TargetOpcode::G_FDIV ||
6385 Opc == TargetOpcode::G_FMAD ||
Opc == TargetOpcode::G_FMA);
6397 Opc = TargetOpcode::G_FSUB;
6402 Opc = TargetOpcode::G_FADD;
6408 else if ((
Opc == TargetOpcode::G_FMUL ||
Opc == TargetOpcode::G_FDIV ||
6409 Opc == TargetOpcode::G_FMAD ||
Opc == TargetOpcode::G_FMA) &&
6418 MI.setDesc(
B.getTII().get(
Opc));
6419 MI.getOperand(1).setReg(
X);
6420 MI.getOperand(2).setReg(
Y);
6428 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
6431 MatchInfo =
MI.getOperand(2).getReg();
6432 LLT Ty =
MRI.getType(
MI.getOperand(0).getReg());
6434 const auto LHSCst = Ty.isVector()
6441 if (LHSCst->Value.isNegZero())
6445 if (LHSCst->Value.isPosZero())
6455 Dst,
Builder.buildFCanonicalize(
MRI.getType(Dst), MatchInfo).getReg(0));
6462 if (
MI.getOpcode() != TargetOpcode::G_FMUL)
6476 bool &AllowFusionGlobally,
6478 bool CanReassociate)
const {
6480 auto *MF =
MI.getMF();
6481 const auto &TLI = *MF->getSubtarget().getTargetLowering();
6483 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
6491 bool HasFMA = TLI.isFMAFasterThanFMulAndFAdd(*MF, DstType) &&
6494 if (!HasFMAD && !HasFMA)
6502 Aggressive = TLI.enableAggressiveFMAFusion(DstType);
6509 assert(
MI.getOpcode() == TargetOpcode::G_FADD);
6511 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6523 unsigned PreferredFusedOpcode =
6524 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6537 unsigned Flags =
MI.getFlags() & LHS.MI->getFlags();
6539 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6540 {LHS.MI->getOperand(1).getReg(),
6541 LHS.MI->getOperand(2).getReg(), RHS.Reg},
6550 unsigned Flags =
MI.getFlags() & RHS.MI->getFlags();
6552 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6553 {RHS.MI->getOperand(1).getReg(),
6554 RHS.MI->getOperand(2).getReg(), LHS.Reg},
6566 assert(
MI.getOpcode() == TargetOpcode::G_FADD);
6568 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6572 const auto &TLI = *
MI.getMF()->getSubtarget().getTargetLowering();
6581 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
6583 unsigned PreferredFusedOpcode =
6584 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6598 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6600 unsigned Flags =
MI.getFlags() & FpExtSrc->
getFlags();
6604 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6605 {FpExtX.getReg(0), FpExtY.getReg(0), RHS.Reg}, Flags);
6614 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6616 unsigned Flags =
MI.getFlags() & FpExtSrc->
getFlags();
6620 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6621 {FpExtX.getReg(0), FpExtY.getReg(0), LHS.Reg}, Flags);
6632 assert(
MI.getOpcode() == TargetOpcode::G_FADD);
6634 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6646 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6648 unsigned PreferredFusedOpcode =
6649 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6654 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6657 MRI.hasOneNonDBGUse(LHS.MI->getOperand(0).getReg()) &&
6658 MRI.hasOneNonDBGUse(LHS.MI->getOperand(3).getReg())) {
6663 else if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6666 MRI.hasOneNonDBGUse(RHS.MI->getOperand(0).getReg()) &&
6667 MRI.hasOneNonDBGUse(RHS.MI->getOperand(3).getReg())) {
6676 Register X = FMA->getOperand(1).getReg();
6677 Register Y = FMA->getOperand(2).getReg();
6680 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6681 unsigned OuterFlags =
MI.getFlags() & FMA->getFlags();
6684 Register InnerFMA =
MRI.createGenericVirtualRegister(DstTy);
6685 B.buildInstr(PreferredFusedOpcode, {InnerFMA}, {U, V, Z}, InnerFlags);
6686 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6687 {
X,
Y, InnerFMA}, OuterFlags);
6698 assert(
MI.getOpcode() == TargetOpcode::G_FADD);
6700 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6707 const auto &TLI = *
MI.getMF()->getSubtarget().getTargetLowering();
6708 LLT DstType =
MRI.getType(
MI.getOperand(0).getReg());
6718 unsigned PreferredFusedOpcode =
6719 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6733 Register FpExtU =
B.buildFPExt(DstType, U).getReg(0);
6734 Register FpExtV =
B.buildFPExt(DstType, V).getReg(0);
6735 Register InnerFMA =
B.buildInstr(PreferredFusedOpcode, {DstType},
6736 {FpExtU, FpExtV, Z}, InnerFlags)
6738 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6739 {
X,
Y, InnerFMA}, OuterFlags);
6745 if (LHS.MI->getOpcode() == PreferredFusedOpcode &&
6749 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6751 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6752 unsigned OuterFlags =
MI.getFlags() & LHS.MI->getFlags();
6756 LHS.MI->getOperand(1).getReg(),
6757 LHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags,
B);
6768 FMAMI->
getOpcode() == PreferredFusedOpcode) {
6773 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6775 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6776 unsigned OuterFlags =
MI.getFlags() & FMAMI->
getFlags();
6780 X =
B.buildFPExt(DstType,
X).getReg(0);
6781 Y =
B.buildFPExt(DstType,
Y).getReg(0);
6784 InnerFlags, OuterFlags,
B);
6793 if (RHS.MI->getOpcode() == PreferredFusedOpcode &&
6797 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6799 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6800 unsigned OuterFlags =
MI.getFlags() & RHS.MI->getFlags();
6804 RHS.MI->getOperand(1).getReg(),
6805 RHS.MI->getOperand(2).getReg(), InnerFlags, OuterFlags,
B);
6816 FMAMI->
getOpcode() == PreferredFusedOpcode) {
6821 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstType,
6823 unsigned InnerFlags =
MI.getFlags() & FMulMI->
getFlags();
6824 unsigned OuterFlags =
MI.getFlags() & FMAMI->
getFlags();
6828 X =
B.buildFPExt(DstType,
X).getReg(0);
6829 Y =
B.buildFPExt(DstType,
Y).getReg(0);
6832 InnerFlags, OuterFlags,
B);
6844 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
6846 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6858 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6862 int FirstMulHasFewerUses =
true;
6866 FirstMulHasFewerUses =
false;
6868 unsigned PreferredFusedOpcode =
6869 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6872 if (FirstMulHasFewerUses &&
6875 unsigned Flags =
MI.getFlags() & LHS.MI->getFlags();
6877 Register NegZ =
B.buildFNeg(DstTy, RHS.Reg).getReg(0);
6878 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6879 {LHS.MI->getOperand(1).getReg(),
6880 LHS.MI->getOperand(2).getReg(), NegZ},
6888 unsigned Flags =
MI.getFlags() & RHS.MI->getFlags();
6891 B.buildFNeg(DstTy, RHS.MI->getOperand(1).getReg()).getReg(0);
6892 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6893 {NegY, RHS.MI->getOperand(2).getReg(), LHS.Reg}, Flags);
6904 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
6906 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6912 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6914 unsigned PreferredFusedOpcode =
6915 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6923 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
6927 Register NegZ =
B.buildFNeg(DstTy, RHSReg).getReg(0);
6928 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6939 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
6941 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6955 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
6957 bool AllowFusionGlobally, HasFMAD,
Aggressive;
6963 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
6965 unsigned PreferredFusedOpcode =
6966 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
6973 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
6979 Register NegZ =
B.buildFNeg(DstTy, RHSReg).getReg(0);
6980 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6981 {FpExtX, FpExtY, NegZ}, Flags);
6990 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
6994 Register NegY =
B.buildFNeg(DstTy, FpExtY).getReg(0);
6997 B.buildInstr(PreferredFusedOpcode, {
MI.getOperand(0).getReg()},
6998 {NegY, FpExtZ, LHSReg}, Flags);
7009 assert(
MI.getOpcode() == TargetOpcode::G_FSUB);
7011 bool AllowFusionGlobally, HasFMAD,
Aggressive;
7015 const auto &TLI = *
MI.getMF()->getSubtarget().getTargetLowering();
7016 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
7020 unsigned PreferredFusedOpcode =
7021 HasFMAD ? TargetOpcode::G_FMAD : TargetOpcode::G_FMA;
7025 Register FpExtX =
B.buildFPExt(DstTy,
X).getReg(0);
7026 Register FpExtY =
B.buildFPExt(DstTy,
Y).getReg(0);
7027 B.buildInstr(PreferredFusedOpcode, {Dst}, {FpExtX, FpExtY, Z}, Flags);
7038 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstTy,
7040 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
7042 Register FMAReg =
MRI.createGenericVirtualRegister(DstTy);
7045 B.buildFNeg(
MI.getOperand(0).getReg(), FMAReg);
7055 TLI.isFPExtFoldable(
MI, PreferredFusedOpcode, DstTy,
7057 unsigned Flags =
MI.getFlags() & FMulMI->
getFlags();
7069 unsigned &IdxToPropagate)
const {
7071 switch (
MI.getOpcode()) {
7074 case TargetOpcode::G_FMINNUM:
7075 case TargetOpcode::G_FMAXNUM:
7076 PropagateNaN =
false;
7078 case TargetOpcode::G_FMINIMUM:
7079 case TargetOpcode::G_FMAXIMUM:
7080 PropagateNaN =
true;
7084 auto MatchNaN = [&](
unsigned Idx) {
7085 Register MaybeNaNReg =
MI.getOperand(Idx).getReg();
7089 IdxToPropagate = PropagateNaN ? Idx : (Idx == 1 ? 2 : 1);
7093 return MatchNaN(1) || MatchNaN(2);
7101 assert(
MI.getOpcode() == TargetOpcode::G_FDIV);
7111 return N0CFP && (N0CFP->isOne() || N0CFP->isMinusOne());
7128 for (
auto &U :
MRI.use_nodbg_instructions(
Y)) {
7129 if (&U == &
MI || U.getParent() !=
MI.getParent())
7131 if (U.getOpcode() == TargetOpcode::G_FDIV &&
7132 U.getOperand(2).getReg() ==
Y && U.getOperand(1).getReg() !=
Y &&
7133 !IsOne(U.getOperand(1).getReg())) {
7146 return MatchInfo.
size() >= MinUses;
7154 LLT Ty =
MRI.getType(MatchInfo[0]->getOperand(0).
getReg());
7155 auto Div =
Builder.buildFDiv(Ty,
Builder.buildFConstant(Ty, 1.0),
7156 MatchInfo[0]->getOperand(2).getReg(),
7157 MatchInfo[0]->getFlags());
7162 Builder.buildFMul(
MI->getOperand(0).getReg(),
MI->getOperand(1).getReg(),
7163 Div->getOperand(0).getReg(),
MI->getFlags());
7164 MI->eraseFromParent();
7169 assert(
MI.getOpcode() == TargetOpcode::G_ADD &&
"Expected a G_ADD");
7179 Reg == MaybeSameReg;
7181 return CheckFold(LHS, RHS) || CheckFold(RHS, LHS);
7202 LLT DstVecTy =
MRI.getType(
MI.getOperand(0).getReg());
7211 return MRI.getType(MatchInfo) == DstVecTy;
7214 std::optional<ValueAndVReg> ShiftAmount;
7223 return MRI.getType(MatchInfo) == DstVecTy;
7238 return MRI.getType(MatchInfo) ==
MRI.getType(
MI.getOperand(0).getReg());
7245 std::optional<ValueAndVReg> ShiftAmt;
7251 LLT MatchTy =
MRI.getType(MatchInfo);
7252 return ShiftAmt->Value.getZExtValue() == MatchTy.
getSizeInBits() &&
7253 MatchTy ==
MRI.getType(
MI.getOperand(0).getReg());
7256unsigned CombinerHelper::getFPMinMaxOpcForSelect(
7258 SelectPatternNaNBehaviour VsNaNRetVal)
const {
7259 assert(VsNaNRetVal != SelectPatternNaNBehaviour::NOT_APPLICABLE &&
7260 "Expected a NaN behaviour?");
7270 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7271 return TargetOpcode::G_FMAXNUM;
7272 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7273 return TargetOpcode::G_FMAXIMUM;
7274 if (
isLegal({TargetOpcode::G_FMAXNUM, {DstTy}}))
7275 return TargetOpcode::G_FMAXNUM;
7276 if (
isLegal({TargetOpcode::G_FMAXIMUM, {DstTy}}))
7277 return TargetOpcode::G_FMAXIMUM;
7283 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_OTHER)
7284 return TargetOpcode::G_FMINNUM;
7285 if (VsNaNRetVal == SelectPatternNaNBehaviour::RETURNS_NAN)
7286 return TargetOpcode::G_FMINIMUM;
7287 if (
isLegal({TargetOpcode::G_FMINNUM, {DstTy}}))
7288 return TargetOpcode::G_FMINNUM;
7289 if (!
isLegal({TargetOpcode::G_FMINIMUM, {DstTy}}))
7291 return TargetOpcode::G_FMINIMUM;
7295CombinerHelper::SelectPatternNaNBehaviour
7297 bool IsOrderedComparison)
const {
7298 bool LHSSafe =
VT->isKnownNeverNaN(
LHS);
7299 bool RHSSafe =
VT->isKnownNeverNaN(
RHS);
7301 if (!LHSSafe && !RHSSafe)
7302 return SelectPatternNaNBehaviour::NOT_APPLICABLE;
7303 if (LHSSafe && RHSSafe)
7304 return SelectPatternNaNBehaviour::RETURNS_ANY;
7307 if (IsOrderedComparison)
7308 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_NAN
7309 : SelectPatternNaNBehaviour::RETURNS_OTHER;
7312 return LHSSafe ? SelectPatternNaNBehaviour::RETURNS_OTHER
7313 : SelectPatternNaNBehaviour::RETURNS_NAN;
7322 LLT DstTy =
MRI.getType(Dst);
7335 SelectPatternNaNBehaviour ResWithKnownNaNInfo =
7337 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::NOT_APPLICABLE)
7339 if (TrueVal == CmpRHS && FalseVal == CmpLHS) {
7342 if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_NAN)
7343 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_OTHER;
7344 else if (ResWithKnownNaNInfo == SelectPatternNaNBehaviour::RETURNS_OTHER)
7345 ResWithKnownNaNInfo = SelectPatternNaNBehaviour::RETURNS_NAN;
7347 if (TrueVal != CmpLHS || FalseVal != CmpRHS)
7350 unsigned Opc = getFPMinMaxOpcForSelect(Pred, DstTy, ResWithKnownNaNInfo);
7355 if (
Opc != TargetOpcode::G_FMAXIMUM &&
Opc != TargetOpcode::G_FMINIMUM) {
7360 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero()) {
7362 if (!KnownNonZeroSide || !KnownNonZeroSide->Value.isNonZero())
7366 MatchInfo = [=](MachineIRBuilder &
B) {
7367 B.buildInstr(
Opc, {Dst}, {CmpLHS, CmpRHS});
7375 assert(
MI.getOpcode() == TargetOpcode::G_SELECT);
7382 Register TrueVal =
MI.getOperand(2).getReg();
7383 Register FalseVal =
MI.getOperand(3).getReg();
7384 return matchFPSelectToMinMax(Dst,
Cond, TrueVal, FalseVal, MatchInfo);
7389 assert(
MI.getOpcode() == TargetOpcode::G_ICMP);
7402 if (MatchedSub &&
X != OpLHS)
7410 Y =
X == OpLHS ? OpRHS :
X == OpRHS ? OpLHS :
Register();
7413 auto Zero =
B.buildConstant(
MRI.getType(
Y), 0);
7414 B.buildICmp(Pred, Dst,
Y, Zero);
7421static std::optional<unsigned>
7423 std::optional<int64_t> &Result) {
7424 assert((Opcode == TargetOpcode::G_SHL || Opcode == TargetOpcode::G_LSHR ||
7425 Opcode == TargetOpcode::G_ASHR) &&
7426 "Expect G_SHL, G_LSHR or G_ASHR.");
7427 auto SignificantBits = 0;
7429 case TargetOpcode::G_SHL:
7433 case TargetOpcode::G_LSHR:
7437 case TargetOpcode::G_ASHR:
7446 Result = std::nullopt;
7457 Register ShiftVal =
MI.getOperand(1).getReg();
7458 Register ShiftReg =
MI.getOperand(2).getReg();
7459 LLT ResTy =
MRI.getType(
MI.getOperand(0).getReg());
7460 auto IsShiftTooBig = [&](
const Constant *
C) {
7465 MatchInfo = std::nullopt;
7469 MI.getOpcode(), MatchInfo);
7470 return OptMaxUsefulShift && CI->uge(*OptMaxUsefulShift);
7476 unsigned LHSOpndIdx = 1;
7477 unsigned RHSOpndIdx = 2;
7478 switch (
MI.getOpcode()) {
7479 case TargetOpcode::G_UADDO:
7480 case TargetOpcode::G_SADDO:
7481 case TargetOpcode::G_UMULO:
7482 case TargetOpcode::G_SMULO:
7489 Register LHS =
MI.getOperand(LHSOpndIdx).getReg();
7490 Register RHS =
MI.getOperand(RHSOpndIdx).getReg();
7500 if (LHSDef->
getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER)
7504 return RHSDef->
getOpcode() != TargetOpcode::G_CONSTANT_FOLD_BARRIER &&
7511 std::optional<FPValueAndVReg> ValAndVReg;
7519 unsigned LHSOpndIdx = 1;
7520 unsigned RHSOpndIdx = 2;
7521 switch (
MI.getOpcode()) {
7522 case TargetOpcode::G_UADDO:
7523 case TargetOpcode::G_SADDO:
7524 case TargetOpcode::G_UMULO:
7525 case TargetOpcode::G_SMULO:
7532 Register LHSReg =
MI.getOperand(LHSOpndIdx).getReg();
7533 Register RHSReg =
MI.getOperand(RHSOpndIdx).getReg();
7534 MI.getOperand(LHSOpndIdx).setReg(RHSReg);
7535 MI.getOperand(RHSOpndIdx).setReg(LHSReg);
7539bool CombinerHelper::isOneOrOneSplat(
Register Src,
bool AllowUndefs)
const {
7541 if (SrcTy.isFixedVector())
7543 if (SrcTy.isScalar()) {
7547 return IConstant && IConstant->Value == 1;
7552bool CombinerHelper::isZeroOrZeroSplat(
Register Src,
bool AllowUndefs)
const {
7553 LLT SrcTy =
MRI.getType(Src);
7555 return isConstantSplatVector(Src, 0, AllowUndefs);
7560 return IConstant && IConstant->Value == 0;
7567bool CombinerHelper::isConstantSplatVector(
Register Src, int64_t SplatValue,
7568 bool AllowUndefs)
const {
7574 for (
unsigned I = 0;
I < NumSources; ++
I) {
7575 GImplicitDef *ImplicitDef =
7577 if (ImplicitDef && AllowUndefs)
7579 if (ImplicitDef && !AllowUndefs)
7581 std::optional<ValueAndVReg> IConstant =
7583 if (IConstant && IConstant->Value == SplatValue)
7593CombinerHelper::getConstantOrConstantSplatVector(
Register Src)
const {
7596 return IConstant->Value;
7600 return std::nullopt;
7603 std::optional<APInt>
Value = std::nullopt;
7604 for (
unsigned I = 0;
I < NumSources; ++
I) {
7605 std::optional<ValueAndVReg> IConstant =
7608 return std::nullopt;
7610 Value = IConstant->Value;
7611 else if (*
Value != IConstant->Value)
7612 return std::nullopt;
7618bool CombinerHelper::isConstantOrConstantVectorI(
Register Src)
const {
7628 for (
unsigned I = 0;
I < NumSources; ++
I) {
7629 std::optional<ValueAndVReg> IConstant =
7638bool CombinerHelper::tryFoldSelectOfConstants(
GSelect *
Select,
7645 LLT CondTy =
MRI.getType(
Select->getCondReg());
7646 LLT TrueTy =
MRI.getType(
Select->getTrueReg());
7656 std::optional<ValueAndVReg> TrueOpt =
7658 std::optional<ValueAndVReg> FalseOpt =
7661 if (!TrueOpt || !FalseOpt)
7664 APInt TrueValue = TrueOpt->Value;
7665 APInt FalseValue = FalseOpt->Value;
7669 MatchInfo = [=](MachineIRBuilder &
B) {
7670 B.setInstrAndDebugLoc(*
Select);
7671 B.buildZExtOrTrunc(Dest,
Cond);
7678 MatchInfo = [=](MachineIRBuilder &
B) {
7679 B.setInstrAndDebugLoc(*
Select);
7680 B.buildSExtOrTrunc(Dest,
Cond);
7687 MatchInfo = [=](MachineIRBuilder &
B) {
7688 B.setInstrAndDebugLoc(*
Select);
7689 Register Inner =
MRI.createGenericVirtualRegister(CondTy);
7690 B.buildNot(Inner,
Cond);
7691 B.buildZExtOrTrunc(Dest, Inner);
7698 MatchInfo = [=](MachineIRBuilder &
B) {
7699 B.setInstrAndDebugLoc(*
Select);
7700 Register Inner =
MRI.createGenericVirtualRegister(CondTy);
7701 B.buildNot(Inner,
Cond);
7702 B.buildSExtOrTrunc(Dest, Inner);
7708 if (TrueValue - 1 == FalseValue) {
7709 MatchInfo = [=](MachineIRBuilder &
B) {
7710 B.setInstrAndDebugLoc(*
Select);
7711 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7712 B.buildZExtOrTrunc(Inner,
Cond);
7713 B.buildAdd(Dest, Inner, False);
7719 if (TrueValue + 1 == FalseValue) {
7720 MatchInfo = [=](MachineIRBuilder &
B) {
7721 B.setInstrAndDebugLoc(*
Select);
7722 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7723 B.buildSExtOrTrunc(Inner,
Cond);
7724 B.buildAdd(Dest, Inner, False);
7731 MatchInfo = [=](MachineIRBuilder &
B) {
7732 B.setInstrAndDebugLoc(*
Select);
7733 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7734 B.buildZExtOrTrunc(Inner,
Cond);
7737 auto ShAmtC =
B.buildConstant(ShiftTy, TrueValue.
exactLogBase2());
7738 B.buildShl(Dest, Inner, ShAmtC, Flags);
7745 MatchInfo = [=](MachineIRBuilder &
B) {
7746 B.setInstrAndDebugLoc(*
Select);
7748 B.buildNot(Not,
Cond);
7749 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7750 B.buildZExtOrTrunc(Inner, Not);
7753 auto ShAmtC =
B.buildConstant(ShiftTy, FalseValue.
exactLogBase2());
7754 B.buildShl(Dest, Inner, ShAmtC, Flags);
7761 MatchInfo = [=](MachineIRBuilder &
B) {
7762 B.setInstrAndDebugLoc(*
Select);
7763 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7764 B.buildSExtOrTrunc(Inner,
Cond);
7765 B.buildOr(Dest, Inner, False, Flags);
7772 MatchInfo = [=](MachineIRBuilder &
B) {
7773 B.setInstrAndDebugLoc(*
Select);
7775 B.buildNot(Not,
Cond);
7776 Register Inner =
MRI.createGenericVirtualRegister(TrueTy);
7777 B.buildSExtOrTrunc(Inner, Not);
7778 B.buildOr(Dest, Inner, True, Flags);
7787bool CombinerHelper::tryFoldBoolSelectToLogic(
GSelect *
Select,
7794 LLT CondTy =
MRI.getType(
Select->getCondReg());
7795 LLT TrueTy =
MRI.getType(
Select->getTrueReg());
7804 if (CondTy != TrueTy)
7809 if ((
Cond == True) || isOneOrOneSplat(True,
true)) {
7810 MatchInfo = [=](MachineIRBuilder &
B) {
7811 B.setInstrAndDebugLoc(*
Select);
7812 Register Ext =
MRI.createGenericVirtualRegister(TrueTy);
7813 B.buildZExtOrTrunc(Ext,
Cond);
7814 auto FreezeFalse =
B.buildFreeze(TrueTy, False);
7815 B.buildOr(DstReg, Ext, FreezeFalse, Flags);
7822 if ((
Cond == False) || isZeroOrZeroSplat(False,
true)) {
7823 MatchInfo = [=](MachineIRBuilder &
B) {
7824 B.setInstrAndDebugLoc(*
Select);
7825 Register Ext =
MRI.createGenericVirtualRegister(TrueTy);
7826 B.buildZExtOrTrunc(Ext,
Cond);
7827 auto FreezeTrue =
B.buildFreeze(TrueTy, True);
7828 B.buildAnd(DstReg, Ext, FreezeTrue);
7834 if (isOneOrOneSplat(False,
true)) {
7835 MatchInfo = [=](MachineIRBuilder &
B) {
7836 B.setInstrAndDebugLoc(*
Select);
7838 Register Inner =
MRI.createGenericVirtualRegister(CondTy);
7839 B.buildNot(Inner,
Cond);
7841 Register Ext =
MRI.createGenericVirtualRegister(TrueTy);
7842 B.buildZExtOrTrunc(Ext, Inner);
7843 auto FreezeTrue =
B.buildFreeze(TrueTy, True);
7844 B.buildOr(DstReg, Ext, FreezeTrue, Flags);
7850 if (isZeroOrZeroSplat(True,
true)) {
7851 MatchInfo = [=](MachineIRBuilder &
B) {
7852 B.setInstrAndDebugLoc(*
Select);
7854 Register Inner =
MRI.createGenericVirtualRegister(CondTy);
7855 B.buildNot(Inner,
Cond);
7857 Register Ext =
MRI.createGenericVirtualRegister(TrueTy);
7858 B.buildZExtOrTrunc(Ext, Inner);
7859 auto FreezeFalse =
B.buildFreeze(TrueTy, False);
7860 B.buildAnd(DstReg, Ext, FreezeFalse);
7882 LLT DstTy =
MRI.getType(DstReg);
7887 if (!
MRI.hasOneNonDBGUse(CondReg))
7896 if (True == CmpRHS && False == CmpLHS) {
7904 if (True != CmpLHS || False != CmpRHS)
7944 assert(
MI.getOpcode() == TargetOpcode::G_SUB);
7945 Register DestReg =
MI.getOperand(0).getReg();
7946 LLT DestTy =
MRI.getType(DestReg);
7960 if (
isLegal({NewOpc, {DestTy}})) {
7962 B.buildInstr(NewOpc, {DestReg}, {
X, Sub0});
7974 if (tryFoldSelectOfConstants(
Select, MatchInfo))
7977 if (tryFoldBoolSelectToLogic(
Select, MatchInfo))
7987bool CombinerHelper::tryFoldAndOrOrICmpsUsingRanges(
7989 assert(Logic->
getOpcode() != TargetOpcode::G_XOR &&
"unexpected xor");
7990 bool IsAnd = Logic->
getOpcode() == TargetOpcode::G_AND;
7994 unsigned Flags = Logic->
getFlags();
8013 std::optional<ValueAndVReg> MaybeC1 =
8017 C1 = MaybeC1->Value;
8019 std::optional<ValueAndVReg> MaybeC2 =
8023 C2 = MaybeC2->Value;
8044 std::optional<APInt> Offset1;
8045 std::optional<APInt> Offset2;
8048 std::optional<ValueAndVReg> MaybeOffset1 =
8051 R1 =
Add->getLHSReg();
8052 Offset1 = MaybeOffset1->Value;
8056 std::optional<ValueAndVReg> MaybeOffset2 =
8059 R2 =
Add->getLHSReg();
8060 Offset2 = MaybeOffset2->Value;
8079 bool CreateMask =
false;
8092 if (!LowerDiff.
isPowerOf2() || LowerDiff != UpperDiff ||
8105 CR->getEquivalentICmp(NewPred, NewC,
Offset);
8114 MatchInfo = [=](MachineIRBuilder &
B) {
8115 if (CreateMask &&
Offset != 0) {
8116 auto TildeLowerDiff =
B.buildConstant(CmpOperandTy, ~LowerDiff);
8117 auto And =
B.buildAnd(CmpOperandTy, R1, TildeLowerDiff);
8118 auto OffsetC =
B.buildConstant(CmpOperandTy,
Offset);
8119 auto Add =
B.buildAdd(CmpOperandTy,
And, OffsetC, Flags);
8120 auto NewCon =
B.buildConstant(CmpOperandTy, NewC);
8121 auto ICmp =
B.buildICmp(NewPred, CmpTy,
Add, NewCon);
8122 B.buildZExtOrTrunc(DstReg, ICmp);
8123 }
else if (CreateMask &&
Offset == 0) {
8124 auto TildeLowerDiff =
B.buildConstant(CmpOperandTy, ~LowerDiff);
8125 auto And =
B.buildAnd(CmpOperandTy, R1, TildeLowerDiff);
8126 auto NewCon =
B.buildConstant(CmpOperandTy, NewC);
8127 auto ICmp =
B.buildICmp(NewPred, CmpTy,
And, NewCon);
8128 B.buildZExtOrTrunc(DstReg, ICmp);
8129 }
else if (!CreateMask &&
Offset != 0) {
8130 auto OffsetC =
B.buildConstant(CmpOperandTy,
Offset);
8131 auto Add =
B.buildAdd(CmpOperandTy, R1, OffsetC, Flags);
8132 auto NewCon =
B.buildConstant(CmpOperandTy, NewC);
8133 auto ICmp =
B.buildICmp(NewPred, CmpTy,
Add, NewCon);
8134 B.buildZExtOrTrunc(DstReg, ICmp);
8135 }
else if (!CreateMask &&
Offset == 0) {
8136 auto NewCon =
B.buildConstant(CmpOperandTy, NewC);
8137 auto ICmp =
B.buildICmp(NewPred, CmpTy, R1, NewCon);
8138 B.buildZExtOrTrunc(DstReg, ICmp);
8146bool CombinerHelper::tryFoldLogicOfFCmps(
GLogicalBinOp *Logic,
8152 bool IsAnd = Logic->
getOpcode() == TargetOpcode::G_AND;
8164 LLT CmpTy =
MRI.getType(Cmp1->
getReg(0));
8170 {TargetOpcode::G_FCMP, {CmpTy, CmpOperandTy}}) ||
8171 !
MRI.hasOneNonDBGUse(Logic->
getReg(0)) ||
8172 !
MRI.hasOneNonDBGUse(Cmp1->
getReg(0)) ||
8173 !
MRI.hasOneNonDBGUse(Cmp2->
getReg(0)) ||
8184 if (LHS0 == RHS1 && LHS1 == RHS0) {
8190 if (LHS0 == RHS0 && LHS1 == RHS1) {
8194 unsigned NewPred = IsAnd ? CmpCodeL & CmpCodeR : CmpCodeL | CmpCodeR;
8196 MatchInfo = [=](MachineIRBuilder &
B) {
8201 auto False =
B.buildConstant(CmpTy, 0);
8202 B.buildZExtOrTrunc(DestReg, False);
8209 B.buildZExtOrTrunc(DestReg, True);
8211 auto Cmp =
B.buildFCmp(Pred, CmpTy, LHS0, LHS1, Flags);
8212 B.buildZExtOrTrunc(DestReg, Cmp);
8224 if (tryFoldAndOrOrICmpsUsingRanges(
And, MatchInfo))
8227 if (tryFoldLogicOfFCmps(
And, MatchInfo))
8236 if (tryFoldAndOrOrICmpsUsingRanges(
Or, MatchInfo))
8239 if (tryFoldLogicOfFCmps(
Or, MatchInfo))
8254 bool IsSigned =
Add->isSigned();
8255 LLT DstTy =
MRI.getType(Dst);
8256 LLT CarryTy =
MRI.getType(Carry);
8259 if (
MRI.use_nodbg_empty(Carry) &&
8262 B.buildAdd(Dst, LHS, RHS);
8263 B.buildUndef(Carry);
8269 if (isConstantOrConstantVectorI(LHS) && !isConstantOrConstantVectorI(RHS)) {
8272 B.buildSAddo(Dst, Carry, RHS, LHS);
8278 B.buildUAddo(Dst, Carry, RHS, LHS);
8283 std::optional<APInt> MaybeLHS = getConstantOrConstantSplatVector(LHS);
8284 std::optional<APInt> MaybeRHS = getConstantOrConstantSplatVector(RHS);
8290 APInt Result = IsSigned ? MaybeLHS->sadd_ov(*MaybeRHS, Overflow)
8291 : MaybeLHS->uadd_ov(*MaybeRHS, Overflow);
8293 B.buildConstant(Dst, Result);
8294 B.buildConstant(Carry, Overflow);
8302 B.buildCopy(Dst, LHS);
8303 B.buildConstant(Carry, 0);
8312 if (MaybeRHS && AddLHS &&
MRI.hasOneNonDBGUse(
Add->getReg(0)) &&
8315 std::optional<APInt> MaybeAddRHS =
8316 getConstantOrConstantSplatVector(AddLHS->
getRHSReg());
8319 APInt NewC = IsSigned ? MaybeAddRHS->sadd_ov(*MaybeRHS, Overflow)
8320 : MaybeAddRHS->uadd_ov(*MaybeRHS, Overflow);
8324 auto ConstRHS =
B.buildConstant(DstTy, NewC);
8325 B.buildSAddo(Dst, Carry, AddLHS->
getLHSReg(), ConstRHS);
8331 auto ConstRHS =
B.buildConstant(DstTy, NewC);
8332 B.buildUAddo(Dst, Carry, AddLHS->
getLHSReg(), ConstRHS);
8357 B.buildConstant(Carry, 0);
8364 B.buildAdd(Dst, LHS, RHS);
8365 B.buildConstant(Carry, 1);
8377 if (
VT->computeNumSignBits(RHS) > 1 &&
VT->computeNumSignBits(LHS) > 1) {
8380 B.buildConstant(Carry, 0);
8396 B.buildConstant(Carry, 0);
8403 B.buildAdd(Dst, LHS, RHS);
8404 B.buildConstant(Carry, 1);
8422 bool OptForSize =
MI.getMF()->getFunction().hasOptSize();
8428 auto [Dst,
Base] =
MI.getFirst2Regs();
8429 LLT Ty =
MRI.getType(Dst);
8433 Builder.buildFConstant(Dst, 1.0);
8434 MI.removeFromParent();
8446 std::optional<SrcOp> Res;
8448 while (ExpVal > 0) {
8453 Res =
Builder.buildFMul(Ty, *Res, CurSquare);
8456 CurSquare =
Builder.buildFMul(Ty, CurSquare, CurSquare);
8463 Res =
Builder.buildFDiv(Ty,
Builder.buildFConstant(Ty, 1.0), *Res,
8467 MI.eraseFromParent();
8478 if (!
MRI.hasOneNonDBGUse(
Sub->getLHSReg()))
8485 LLT DstTy =
MRI.getType(Dst);
8488 auto Const =
B.buildConstant(DstTy, C1 - C2);
8489 B.buildAdd(Dst,
A, Const);
8503 if (!
MRI.hasOneNonDBGUse(
Sub->getRHSReg()))
8510 LLT DstTy =
MRI.getType(Dst);
8513 auto Const =
B.buildConstant(DstTy, C2 - C1);
8514 B.buildSub(Dst, Const,
A);
8535 LLT DstTy =
MRI.getType(Dst);
8538 auto Const =
B.buildConstant(DstTy, C1 + C2);
8539 B.buildSub(Dst,
A, Const);
8560 LLT DstTy =
MRI.getType(Dst);
8563 auto Const =
B.buildConstant(DstTy, C1 - C2);
8564 B.buildSub(Dst, Const,
A);
8578 if (!
MRI.hasOneNonDBGUse(
Add->getLHSReg()))
8585 LLT DstTy =
MRI.getType(Dst);
8588 auto Const =
B.buildConstant(DstTy, C2 - C1);
8589 B.buildAdd(Dst,
A, Const);
8633 if (!
MRI.hasOneNonDBGUse(BV->
getReg(0)))
8641 LLT SmallBvTy = DstTy;
8645 {TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
8650 {TargetOpcode::G_ANYEXT,
8662 auto AnyExt =
B.buildAnyExt(SmallBvElemenTy, SourceArray);
8663 Ops.push_back(AnyExt.getReg(0));
8681 const LLT SrcTy =
MRI.getType(Shuffle.getSrc1Reg());
8682 const unsigned NumSrcElems = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
8683 const unsigned NumDstElts = OrigMask.
size();
8684 for (
unsigned i = 0; i != NumDstElts; ++i) {
8685 int Idx = OrigMask[i];
8686 if (Idx >= (
int)NumSrcElems) {
8697 B.buildShuffleVector(
MI.getOperand(0),
MI.getOperand(1),
MI.getOperand(2),
8698 std::move(NewMask));
8705 const unsigned MaskSize = Mask.size();
8706 for (
unsigned I = 0;
I < MaskSize; ++
I) {
8711 if (Idx < (
int)NumElems)
8712 Mask[
I] = Idx + NumElems;
8714 Mask[
I] = Idx - NumElems;
8724 if (
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc1Reg(),
MRI))
8727 if (
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, Shuffle.getSrc2Reg(),
MRI))
8730 const LLT DstTy =
MRI.getType(Shuffle.getReg(0));
8731 const LLT Src1Ty =
MRI.getType(Shuffle.getSrc1Reg());
8733 {TargetOpcode::G_SHUFFLE_VECTOR, {DstTy, Src1Ty}}))
8737 const unsigned NumSrcElems = Src1Ty.getNumElements();
8739 bool TouchesSrc1 =
false;
8740 bool TouchesSrc2 =
false;
8741 const unsigned NumElems = Mask.size();
8742 for (
unsigned Idx = 0; Idx < NumElems; ++Idx) {
8746 if (Mask[Idx] < (
int)NumSrcElems)
8752 if (TouchesSrc1 == TouchesSrc2)
8755 Register NewSrc1 = Shuffle.getSrc1Reg();
8758 NewSrc1 = Shuffle.getSrc2Reg();
8763 auto Undef =
B.buildUndef(Src1Ty);
8764 B.buildShuffleVector(Shuffle.getReg(0), NewSrc1,
Undef, NewMask);
8778 LLT DstTy =
MRI.getType(Dst);
8779 LLT CarryTy =
MRI.getType(Carry);
8801 B.buildConstant(Carry, 0);
8808 B.buildSub(Dst, LHS, RHS);
8826 B.buildConstant(Carry, 0);
8833 B.buildSub(Dst, LHS, RHS);
8850 CtlzMI.
getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON) &&
8851 "Expected G_CTLZ variant");
8856 LLT Ty =
MRI.getType(Dst);
8857 LLT SrcTy =
MRI.getType(Src);
8859 if (!(Ty.isValid() && Ty.isScalar()))
8868 switch (
LI->getAction(Query).Action) {
8879 bool NeedAdd =
true;
8887 unsigned BitWidth = Ty.getScalarSizeInBits();
8898 B.buildCTLS(Dst,
X);
8902 auto Ctls =
B.buildCTLS(Ty,
X);
8903 auto One =
B.buildConstant(Ty, 1);
8905 B.buildAdd(Dst, Ctls, One);
8915 unsigned TargetOpc)
const {
8916 assert((
MI.getOpcode() == TargetOpcode::G_LSHR ||
8917 MI.getOpcode() == TargetOpcode::G_ASHR) &&
8918 "Expected G_LSHR/G_ASHR");
8921 return XTy ==
MRI.getType(
Y) &&
isLegal({TargetOpc, {XTy}});
8925 assert((
MI.getOpcode() == TargetOpcode::G_CTLZ ||
8926 MI.getOpcode() == TargetOpcode::G_CTTZ) &&
8927 "Expected count-zero opcode");
8928 switch (
MI.getOpcode()) {
8929 case TargetOpcode::G_CTLZ:
8930 return TargetOpcode::G_CTLZ_ZERO_POISON;
8931 case TargetOpcode::G_CTTZ:
8932 return TargetOpcode::G_CTTZ_ZERO_POISON;
8944 if (!
VT->isKnownNeverZero(Src))
8947 LLT DstTy =
MRI.getType(
MI.getOperand(0).getReg());
8948 LLT SrcTy =
MRI.getType(Src);