102#define DEBUG_TYPE "peephole-opt"
107 cl::desc(
"Aggressive extension optimization"));
111 cl::desc(
"Disable the peephole optimizer"));
118 cl::desc(
"Disable advanced copy optimization"));
122 cl::desc(
"Disable non-allocatable physical register copy optimization"));
128 cl::desc(
"Limit the length of PHI chains to lookup"));
134 cl::desc(
"Maximum length of recurrence chain when evaluating the benefit "
135 "of commuting operands"));
138STATISTIC(NumReuse,
"Number of extension results reused");
140STATISTIC(NumImmFold,
"Number of move immediate folded");
143STATISTIC(NumUncoalescableCopies,
"Number of uncoalescable copies optimized");
144STATISTIC(NumRewrittenCopies,
"Number of copies rewritten");
145STATISTIC(NumNAPhysCopies,
"Number of non-allocatable physical copies removed");
149 class ValueTrackerResult;
150 class RecurrenceInstr;
182 .
set(MachineFunctionProperties::Property::IsSSA);
202 bool findNextSource(
RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap);
213 bool findTargetRecurrence(
Register Reg,
215 RecurrenceCycle &RC);
232 bool foldRedundantNAPhysCopy(
244 (
MI.isRegSequence() ||
MI.isInsertSubreg() ||
245 MI.isExtractSubreg()));
251 return MI.isBitcast() ||
253 (
MI.isRegSequenceLike() ||
MI.isInsertSubregLike() ||
254 MI.isExtractSubregLike()));
274 unsigned SrcSubReg =
MI.getOperand(1).getSubReg();
275 if (!SrcReg.
isVirtual() && !
MRI->isConstantPhysReg(SrcReg))
286 if (!getCopySrc(
MI, SrcPair))
289 auto It = CopySrcMIs.
find(SrcPair);
290 if (It != CopySrcMIs.
end() && It->second == &
MI)
291 CopySrcMIs.
erase(It);
295 deleteChangedCopy(
MI);
300 deleteChangedCopy(
MI);
310 class RecurrenceInstr {
312 using IndexPair = std::pair<unsigned, unsigned>;
315 RecurrenceInstr(
MachineInstr *MI,
unsigned Idx1,
unsigned Idx2)
316 :
MI(
MI), CommutePair(
std::make_pair(Idx1, Idx2)) {}
319 std::optional<IndexPair> getCommutePair()
const {
return CommutePair; }
323 std::optional<IndexPair> CommutePair;
329 class ValueTrackerResult {
338 ValueTrackerResult() =
default;
344 bool isValid()
const {
return getNumSources() > 0; }
354 void addSource(
Register SrcReg,
unsigned SrcSubReg) {
358 void setSource(
int Idx,
Register SrcReg,
unsigned SrcSubReg) {
359 assert(
Idx < getNumSources() &&
"Reg pair source out of index");
363 int getNumSources()
const {
return RegSrcs.
size(); }
370 assert(
Idx < getNumSources() &&
"Reg source out of index");
371 return RegSrcs[
Idx].Reg;
374 unsigned getSrcSubReg(
int Idx)
const {
375 assert(
Idx < getNumSources() &&
"SubReg source out of index");
376 return RegSrcs[
Idx].SubReg;
380 if (
Other.getInst() != getInst())
383 if (
Other.getNumSources() != getNumSources())
386 for (
int i = 0, e =
Other.getNumSources(); i != e; ++i)
387 if (
Other.getSrcReg(i) != getSrcReg(i) ||
388 Other.getSrcSubReg(i) != getSrcSubReg(i))
431 ValueTrackerResult getNextSourceImpl();
434 ValueTrackerResult getNextSourceFromCopy();
437 ValueTrackerResult getNextSourceFromBitcast();
440 ValueTrackerResult getNextSourceFromRegSequence();
443 ValueTrackerResult getNextSourceFromInsertSubreg();
446 ValueTrackerResult getNextSourceFromExtractSubreg();
449 ValueTrackerResult getNextSourceFromSubregToReg();
452 ValueTrackerResult getNextSourceFromPHI();
464 ValueTracker(
Register Reg,
unsigned DefSubReg,
468 if (!
Reg.isPhysical()) {
469 Def =
MRI.getVRegDef(Reg);
470 DefIdx =
MRI.def_begin(Reg).getOperandNo();
479 ValueTrackerResult getNextSource();
484char PeepholeOptimizer::ID = 0;
489 "Peephole Optimizations",
false,
false)
503bool PeepholeOptimizer::
508 if (!
TII->isCoalescableExtInstr(
MI, SrcReg, DstReg, SubIdx))
514 if (
MRI->hasOneNonDBGUse(SrcReg))
521 DstRC =
TRI->getSubClassWithSubReg(DstRC, SubIdx);
531 TRI->getSubClassWithSubReg(
MRI->getRegClass(SrcReg), SubIdx) !=
nullptr;
537 ReachedBBs.
insert(UI.getParent());
545 bool ExtendLife =
true;
557 if (UseSrcSubIdx && UseMO.getSubReg() != SubIdx)
581 if (UseMBB == &
MBB) {
583 if (!LocalMIs.count(
UseMI))
584 Uses.push_back(&UseMO);
585 }
else if (ReachedBBs.
count(UseMBB)) {
588 Uses.push_back(&UseMO);
601 if (ExtendLife && !ExtendedUses.
empty())
606 bool Changed =
false;
615 PHIBBs.
insert(UI.getParent());
621 if (PHIBBs.
count(UseMBB))
626 MRI->clearKillFlags(DstReg);
627 MRI->constrainRegClass(DstReg, DstRC);
649 TII->get(TargetOpcode::COPY), NewVR)
650 .
addReg(DstReg, 0, SubIdx);
654 UseMO->setReg(NewVR);
671 int64_t CmpMask, CmpValue;
678 if (
TII->optimizeCompareInstr(
MI, SrcReg, SrcReg2, CmpMask, CmpValue,
MRI)) {
691 unsigned FalseOp = 0;
692 bool Optimizable =
false;
694 if (
TII->analyzeSelect(
MI,
Cond, TrueOp, FalseOp, Optimizable))
698 if (!
TII->optimizeSelect(
MI, LocalMIs))
701 MI.eraseFromParent();
708 return TII->optimizeCondBranch(
MI);
722bool PeepholeOptimizer::findNextSource(
RegSubRegPair RegSubReg,
723 RewriteMapTy &RewriteMap) {
729 if (
Reg.isPhysical())
737 unsigned PHICount = 0;
749 ValueTrackerResult Res = ValTracker.getNextSource();
755 ValueTrackerResult CurSrcRes = RewriteMap.lookup(CurSrcPair);
756 if (CurSrcRes.isValid()) {
757 assert(CurSrcRes == Res &&
"ValueTrackerResult found must match");
760 if (CurSrcRes.getNumSources() > 1) {
762 <<
"findNextSource: found PHI cycle, aborting...\n");
767 RewriteMap.insert(std::make_pair(CurSrcPair, Res));
771 unsigned NumSrcs = Res.getNumSources();
779 for (
unsigned i = 0; i < NumSrcs; ++i)
784 CurSrcPair = Res.getSrc(0);
794 if (!
TRI->shouldRewriteCopySrc(DefRC, RegSubReg.
SubReg, SrcRC,
800 if (PHICount > 0 && CurSrcPair.
SubReg != 0)
806 }
while (!SrcToLook.
empty());
809 return CurSrcPair.
Reg !=
Reg;
821 assert(!SrcRegs.
empty() &&
"No sources to create a PHI instruction?");
826 assert(SrcRegs[0].
SubReg == 0 &&
"should not have subreg operand");
830 TII.get(TargetOpcode::PHI), NewVR);
832 unsigned MBBOpIdx = 2;
834 MIB.
addReg(RegPair.Reg, 0, RegPair.SubReg);
839 MRI.clearKillFlags(RegPair.Reg);
852 unsigned CurrentSrcIdx = 0;
855 virtual ~Rewriter() =
default;
887 virtual bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg) = 0;
891class CopyRewriter :
public Rewriter {
894 assert(
MI.isCopy() &&
"Expected copy instruction");
896 virtual ~CopyRewriter() =
default;
901 if (CurrentSrcIdx > 0)
915 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
916 if (CurrentSrcIdx != 1)
927class UncoalescableRewriter :
public Rewriter {
932 NumDefs =
MI.getDesc().getNumDefs();
942 if (CurrentSrcIdx == NumDefs)
945 while (CopyLike.getOperand(CurrentSrcIdx).isDead()) {
947 if (CurrentSrcIdx == NumDefs)
960 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
966class InsertSubregRewriter :
public Rewriter {
969 assert(
MI.isInsertSubreg() &&
"Invalid instruction");
986 if (CurrentSrcIdx == 2)
1000 (
unsigned)CopyLike.getOperand(3).getImm());
1004 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
1005 if (CurrentSrcIdx != 2)
1016class ExtractSubregRewriter :
public Rewriter {
1022 assert(
MI.isExtractSubreg() &&
"Invalid instruction");
1033 if (CurrentSrcIdx == 1)
1043 CopyLike.getOperand(2).getImm());
1051 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
1053 if (CurrentSrcIdx != 1)
1056 CopyLike.getOperand(CurrentSrcIdx).setReg(NewReg);
1067 CopyLike.removeOperand(2);
1069 CopyLike.setDesc(
TII.get(TargetOpcode::COPY));
1072 CopyLike.getOperand(CurrentSrcIdx + 1).setImm(NewSubReg);
1078class RegSequenceRewriter :
public Rewriter {
1081 assert(
MI.isRegSequence() &&
"Invalid instruction");
1105 if (CurrentSrcIdx == 0) {
1110 if (CurrentSrcIdx >= CopyLike.getNumOperands())
1113 const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx);
1114 Src.Reg = MOInsertedReg.
getReg();
1116 if ((Src.SubReg = MOInsertedReg.
getSubReg()))
1121 Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm();
1124 Dst.Reg = MODef.
getReg();
1129 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
1132 if ((CurrentSrcIdx & 1) != 1 || CurrentSrcIdx > CopyLike.getNumOperands())
1149 if (
MI.isBitcast() ||
MI.isRegSequenceLike() ||
MI.isInsertSubregLike() ||
1150 MI.isExtractSubregLike())
1151 return new UncoalescableRewriter(
MI);
1153 switch (
MI.getOpcode()) {
1156 case TargetOpcode::COPY:
1157 return new CopyRewriter(
MI);
1158 case TargetOpcode::INSERT_SUBREG:
1159 return new InsertSubregRewriter(
MI);
1160 case TargetOpcode::EXTRACT_SUBREG:
1161 return new ExtractSubregRewriter(
MI,
TII);
1162 case TargetOpcode::REG_SEQUENCE:
1163 return new RegSequenceRewriter(
MI);
1177 bool HandleMultipleSources =
true) {
1180 ValueTrackerResult Res = RewriteMap.
lookup(LookupSrc);
1186 unsigned NumSrcs = Res.getNumSources();
1188 LookupSrc.
Reg = Res.getSrcReg(0);
1189 LookupSrc.
SubReg = Res.getSrcSubReg(0);
1194 if (!HandleMultipleSources)
1200 for (
unsigned i = 0; i < NumSrcs; ++i) {
1201 RegSubRegPair PHISrc(Res.getSrcReg(i), Res.getSrcSubReg(i));
1230bool PeepholeOptimizer::optimizeCoalescableCopy(
MachineInstr &
MI) {
1231 assert(isCoalescableCopy(
MI) &&
"Invalid argument");
1232 assert(
MI.getDesc().getNumDefs() == 1 &&
1233 "Coalescer can understand multiple defs?!");
1239 bool Changed =
false;
1248 while (CpyRewriter->getNextRewritableSource(Src, TrackPair)) {
1250 RewriteMapTy RewriteMap;
1253 if (!findNextSource(TrackPair, RewriteMap))
1260 if (Src.Reg == NewSrc.
Reg || NewSrc.
Reg == 0)
1264 if (CpyRewriter->RewriteCurrentSource(NewSrc.
Reg, NewSrc.
SubReg)) {
1266 MRI->clearKillFlags(NewSrc.
Reg);
1275 NumRewrittenCopies += Changed;
1285PeepholeOptimizer::rewriteSource(
MachineInstr &CopyLike,
1287 assert(!
Def.Reg.isPhysical() &&
"We do not rewrite physical registers");
1294 Register NewVReg =
MRI->createVirtualRegister(DefRC);
1298 TII->get(TargetOpcode::COPY), NewVReg)
1309 MRI->replaceRegWith(
Def.Reg, NewVReg);
1310 MRI->clearKillFlags(NewVReg);
1314 MRI->clearKillFlags(NewSrc.
Reg);
1330bool PeepholeOptimizer::optimizeUncoalescableCopy(
1332 assert(isUncoalescableCopy(
MI) &&
"Invalid argument");
1333 UncoalescableRewriter CpyRewriter(
MI);
1338 RewriteMapTy RewriteMap;
1342 while (CpyRewriter.getNextRewritableSource(Src, Def)) {
1345 if (
Def.Reg.isPhysical())
1350 if (!findNextSource(Def, RewriteMap))
1360 LocalMIs.
insert(&NewCopy);
1365 MI.eraseFromParent();
1366 ++NumUncoalescableCopies;
1373bool PeepholeOptimizer::isLoadFoldable(
1375 if (!
MI.canFoldAsLoad() || !
MI.mayLoad())
1385 if (
Reg.isVirtual() && !
MI.getOperand(0).getSubReg() &&
1386 MRI->hasOneNonDBGUser(Reg)) {
1387 FoldAsLoadDefCandidates.
insert(Reg);
1393bool PeepholeOptimizer::isMoveImmediate(
1397 if (MCID.
getNumDefs() != 1 || !
MI.getOperand(0).isReg())
1400 if (!
Reg.isVirtual())
1404 if (!
MI.isMoveImmediate() && !
TII->getConstValDefinedInReg(
MI, Reg, ImmVal))
1407 ImmDefMIs.
insert(std::make_pair(Reg, &
MI));
1415bool PeepholeOptimizer::foldImmediate(
1419 for (
unsigned i = 0, e =
MI.getDesc().getNumOperands(); i != e; ++i) {
1424 if (!
Reg.isVirtual())
1426 if (ImmDefRegs.
count(Reg) == 0)
1429 assert(
II != ImmDefMIs.
end() &&
"couldn't find immediate definition");
1430 if (
TII->foldImmediate(
MI, *
II->second, Reg,
MRI)) {
1435 if (
MRI->getVRegDef(Reg) &&
1439 MRI->getRegClass(DstReg) ==
MRI->getRegClass(Reg)) {
1440 MRI->replaceRegWith(DstReg, Reg);
1441 MI.eraseFromParent();
1466 assert(
MI.isCopy() &&
"expected a COPY machine instruction");
1469 if (!getCopySrc(
MI, SrcPair))
1476 if (CopySrcMIs.
insert(std::make_pair(SrcPair, &
MI)).second) {
1484 "Unexpected mismatching subreg!");
1492 if (
MRI->getRegClass(DstReg) !=
MRI->getRegClass(PrevDstReg))
1495 MRI->replaceRegWith(DstReg, PrevDstReg);
1498 MRI->clearKillFlags(PrevDstReg);
1502bool PeepholeOptimizer::isNAPhysCopy(
Register Reg) {
1503 return Reg.isPhysical() && !
MRI->isAllocatable(Reg);
1506bool PeepholeOptimizer::foldRedundantNAPhysCopy(
1508 assert(
MI.isCopy() &&
"expected a COPY machine instruction");
1515 if (isNAPhysCopy(SrcReg) && DstReg.
isVirtual()) {
1519 NAPhysToVirtMIs.
insert({SrcReg, &
MI});
1523 if (!(SrcReg.
isVirtual() && isNAPhysCopy(DstReg)))
1527 auto PrevCopy = NAPhysToVirtMIs.
find(DstReg);
1528 if (PrevCopy == NAPhysToVirtMIs.
end()) {
1531 LLVM_DEBUG(
dbgs() <<
"NAPhysCopy: intervening clobber forbids erasing "
1537 if (PrevDstReg == SrcReg) {
1550 NAPhysToVirtMIs.
erase(PrevCopy);
1559bool PeepholeOptimizer::findTargetRecurrence(
1561 RecurrenceCycle &RC) {
1563 if (TargetRegs.
count(Reg))
1571 if (!
MRI->hasOneNonDBGUse(Reg))
1579 unsigned Idx =
MI.findRegisterUseOperandIdx(Reg,
nullptr);
1583 if (
MI.getDesc().getNumDefs() != 1)
1593 unsigned TiedUseIdx;
1594 if (!
MI.isRegTiedToUseOperand(0, &TiedUseIdx))
1597 if (
Idx == TiedUseIdx) {
1598 RC.push_back(RecurrenceInstr(&
MI));
1599 return findTargetRecurrence(DefOp.
getReg(), TargetRegs, RC);
1603 if (
TII->findCommutedOpIndices(
MI,
Idx, CommIdx) && CommIdx == TiedUseIdx) {
1604 RC.push_back(RecurrenceInstr(&
MI,
Idx, CommIdx));
1605 return findTargetRecurrence(DefOp.
getReg(), TargetRegs, RC);
1632 for (
unsigned Idx = 1;
Idx <
PHI.getNumOperands();
Idx += 2) {
1638 bool Changed =
false;
1640 if (findTargetRecurrence(
PHI.getOperand(0).getReg(), TargetRegs, RC)) {
1644 for (
auto &RI : RC) {
1646 auto CP = RI.getCommutePair();
1649 TII->commuteInstruction(*(RI.getMI()),
false, (*CP).first,
1663 LLVM_DEBUG(
dbgs() <<
"********** PEEPHOLE OPTIMIZER **********\n");
1672 DT =
Aggressive ? &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree()
1674 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1677 bool Changed =
false;
1680 bool SeenMoveImm =
false;
1713 if (
MI->isDebugInstr())
1716 if (
MI->isPosition())
1719 if (IsLoopHeader &&
MI->isPHI()) {
1720 if (optimizeRecurrence(*
MI)) {
1726 if (!
MI->isCopy()) {
1731 if (MO.
isDef() && isNAPhysCopy(Reg)) {
1732 const auto &
Def = NAPhysToVirtMIs.
find(Reg);
1733 if (Def != NAPhysToVirtMIs.
end()) {
1737 <<
"NAPhysCopy: invalidating because of " << *
MI);
1738 NAPhysToVirtMIs.
erase(Def);
1743 for (
auto &RegMI : NAPhysToVirtMIs) {
1747 <<
"NAPhysCopy: invalidating because of " << *
MI);
1748 NAPhysToVirtMIs.erase(Def);
1755 if (
MI->isImplicitDef() ||
MI->isKill())
1758 if (
MI->isInlineAsm() ||
MI->hasUnmodeledSideEffects()) {
1765 NAPhysToVirtMIs.clear();
1768 if ((isUncoalescableCopy(*
MI) &&
1769 optimizeUncoalescableCopy(*
MI, LocalMIs)) ||
1770 (
MI->isCompare() && optimizeCmpInstr(*
MI)) ||
1771 (
MI->isSelect() && optimizeSelect(*
MI, LocalMIs))) {
1778 if (
MI->isConditionalBranch() && optimizeCondBranch(*
MI)) {
1783 if (isCoalescableCopy(*
MI) && optimizeCoalescableCopy(*
MI)) {
1789 if (
MI->isCopy() && (foldRedundantCopy(*
MI) ||
1790 foldRedundantNAPhysCopy(*
MI, NAPhysToVirtMIs))) {
1793 MI->eraseFromParent();
1798 if (isMoveImmediate(*
MI, ImmDefRegs, ImmDefMIs)) {
1801 Changed |= optimizeExtInstr(*
MI,
MBB, LocalMIs);
1809 Changed |= foldImmediate(*
MI, ImmDefRegs, ImmDefMIs,
Deleted);
1820 if (!isLoadFoldable(*
MI, FoldAsLoadDefCandidates) &&
1821 !FoldAsLoadDefCandidates.
empty()) {
1829 for (
unsigned i = MIDesc.
getNumDefs(); i !=
MI->getNumOperands();
1835 if (FoldAsLoadDefCandidates.
count(FoldAsLoadDefReg)) {
1840 Register FoldedReg = FoldAsLoadDefReg;
1843 TII->optimizeLoadInstr(*
MI,
MRI, FoldAsLoadDefReg,
DefMI)) {
1852 if (
MI->shouldUpdateCallSiteInfo())
1853 MI->getMF()->moveCallSiteInfo(
MI, FoldMI);
1854 MI->eraseFromParent();
1856 MRI->markUsesInDebugValueAsUndef(FoldedReg);
1857 FoldAsLoadDefCandidates.
erase(FoldedReg);
1871 if (
MI->isLoadFoldBarrier()) {
1873 FoldAsLoadDefCandidates.
clear();
1878 MF.resetDelegate(
this);
1882ValueTrackerResult ValueTracker::getNextSourceFromCopy() {
1883 assert(
Def->isCopy() &&
"Invalid definition");
1888 assert(
Def->getNumOperands() -
Def->getNumImplicitOperands() == 2 &&
1889 "Invalid number of operands");
1890 assert(!
Def->hasImplicitDef() &&
"Only implicit uses are allowed");
1892 if (
Def->getOperand(DefIdx).getSubReg() != DefSubReg)
1895 return ValueTrackerResult();
1899 return ValueTrackerResult();
1900 return ValueTrackerResult(Src.getReg(), Src.getSubReg());
1903ValueTrackerResult ValueTracker::getNextSourceFromBitcast() {
1904 assert(
Def->isBitcast() &&
"Invalid definition");
1907 if (
Def->mayRaiseFPException() ||
Def->hasUnmodeledSideEffects())
1908 return ValueTrackerResult();
1911 if (
Def->getDesc().getNumDefs() != 1)
1912 return ValueTrackerResult();
1917 return ValueTrackerResult();
1919 unsigned SrcIdx =
Def->getNumOperands();
1920 for (
unsigned OpIdx = DefIdx + 1, EndOpIdx = SrcIdx; OpIdx != EndOpIdx;
1928 assert(!MO.
isDef() &&
"We should have skipped all the definitions by now");
1929 if (SrcIdx != EndOpIdx)
1931 return ValueTrackerResult();
1937 if (SrcIdx >=
Def->getNumOperands())
1938 return ValueTrackerResult();
1943 if (
UseMI.isSubregToReg())
1944 return ValueTrackerResult();
1949 return ValueTrackerResult();
1950 return ValueTrackerResult(Src.getReg(), Src.getSubReg());
1953ValueTrackerResult ValueTracker::getNextSourceFromRegSequence() {
1954 assert((
Def->isRegSequence() ||
Def->isRegSequenceLike()) &&
1955 "Invalid definition");
1957 if (
Def->getOperand(DefIdx).getSubReg())
1972 return ValueTrackerResult();
1977 return ValueTrackerResult();
1980 if (!
TII->getRegSequenceInputs(*Def, DefIdx, RegSeqInputRegs))
1981 return ValueTrackerResult();
1987 if (RegSeqInput.SubIdx == DefSubReg)
1988 return ValueTrackerResult(RegSeqInput.Reg, RegSeqInput.SubReg);
1994 return ValueTrackerResult();
1997ValueTrackerResult ValueTracker::getNextSourceFromInsertSubreg() {
1998 assert((
Def->isInsertSubreg() ||
Def->isInsertSubregLike()) &&
1999 "Invalid definition");
2001 if (
Def->getOperand(DefIdx).getSubReg())
2005 return ValueTrackerResult();
2010 return ValueTrackerResult();
2014 if (!
TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg))
2015 return ValueTrackerResult();
2024 if (InsertedReg.
SubIdx == DefSubReg) {
2025 return ValueTrackerResult(InsertedReg.
Reg, InsertedReg.
SubReg);
2034 if (
MRI.getRegClass(MODef.
getReg()) !=
MRI.getRegClass(BaseReg.
Reg) ||
2036 return ValueTrackerResult();
2042 !(
TRI->getSubRegIndexLaneMask(DefSubReg) &
2043 TRI->getSubRegIndexLaneMask(InsertedReg.
SubIdx)).none())
2044 return ValueTrackerResult();
2047 return ValueTrackerResult(BaseReg.
Reg, DefSubReg);
2050ValueTrackerResult ValueTracker::getNextSourceFromExtractSubreg() {
2052 Def->isExtractSubregLike()) &&
"Invalid definition");
2059 return ValueTrackerResult();
2064 return ValueTrackerResult();
2067 if (!
TII->getExtractSubregInputs(*Def, DefIdx, ExtractSubregInputReg))
2068 return ValueTrackerResult();
2072 if (ExtractSubregInputReg.
SubReg)
2073 return ValueTrackerResult();
2075 return ValueTrackerResult(ExtractSubregInputReg.
Reg,
2076 ExtractSubregInputReg.
SubIdx);
2079ValueTrackerResult ValueTracker::getNextSourceFromSubregToReg() {
2080 assert(
Def->isSubregToReg() &&
"Invalid definition");
2088 if (DefSubReg !=
Def->getOperand(3).getImm())
2089 return ValueTrackerResult();
2092 if (
Def->getOperand(2).getSubReg())
2093 return ValueTrackerResult();
2095 return ValueTrackerResult(
Def->getOperand(2).getReg(),
2096 Def->getOperand(3).getImm());
2100ValueTrackerResult ValueTracker::getNextSourceFromPHI() {
2101 assert(
Def->isPHI() &&
"Invalid definition");
2102 ValueTrackerResult Res;
2106 if (
Def->getOperand(0).getSubReg() != DefSubReg)
2107 return ValueTrackerResult();
2110 for (
unsigned i = 1, e =
Def->getNumOperands(); i < e; i += 2) {
2116 return ValueTrackerResult();
2123ValueTrackerResult ValueTracker::getNextSourceImpl() {
2124 assert(Def &&
"This method needs a valid definition");
2126 assert(((
Def->getOperand(DefIdx).isDef() &&
2127 (DefIdx < Def->
getDesc().getNumDefs() ||
2128 Def->getDesc().isVariadic())) ||
2129 Def->getOperand(DefIdx).isImplicit()) &&
2132 return getNextSourceFromCopy();
2133 if (
Def->isBitcast())
2134 return getNextSourceFromBitcast();
2138 return ValueTrackerResult();
2139 if (
Def->isRegSequence() ||
Def->isRegSequenceLike())
2140 return getNextSourceFromRegSequence();
2141 if (
Def->isInsertSubreg() ||
Def->isInsertSubregLike())
2142 return getNextSourceFromInsertSubreg();
2143 if (
Def->isExtractSubreg() ||
Def->isExtractSubregLike())
2144 return getNextSourceFromExtractSubreg();
2145 if (
Def->isSubregToReg())
2146 return getNextSourceFromSubregToReg();
2148 return getNextSourceFromPHI();
2149 return ValueTrackerResult();
2152ValueTrackerResult ValueTracker::getNextSource() {
2156 return ValueTrackerResult();
2158 ValueTrackerResult Res = getNextSourceImpl();
2159 if (Res.isValid()) {
2163 bool OneRegSrc = Res.getNumSources() == 1;
2165 Reg = Res.getSrcReg(0);
2172 if (!
Reg.isPhysical() && OneRegSrc) {
2174 if (DI !=
MRI.def_end()) {
2177 DefSubReg = Res.getSrcSubReg(0);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static void clear(coro::Shape &Shape)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
std::optional< std::vector< StOtherPiece > > Other
Rewrite Partial Register Uses
const HexagonInstrInfo * TII
A common definition of LaneBitmask for use in TableGen and CodeGen.
unsigned const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
TargetInstrInfo::RegSubRegPair RegSubRegPair
static cl::opt< unsigned > RewritePHILimit("rewrite-phi-limit", cl::Hidden, cl::init(10), cl::desc("Limit the length of PHI chains to lookup"))
static cl::opt< bool > DisablePeephole("disable-peephole", cl::Hidden, cl::init(false), cl::desc("Disable the peephole optimizer"))
static cl::opt< unsigned > MaxRecurrenceChain("recurrence-chain-limit", cl::Hidden, cl::init(3), cl::desc("Maximum length of recurrence chain when evaluating the benefit " "of commuting operands"))
static cl::opt< bool > DisableNAPhysCopyOpt("disable-non-allocatable-phys-copy-opt", cl::Hidden, cl::init(false), cl::desc("Disable non-allocatable physical register copy optimization"))
static bool isVirtualRegisterOperand(MachineOperand &MO)
\bried Returns true if MO is a virtual register operand.
static MachineInstr & insertPHI(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const SmallVectorImpl< RegSubRegPair > &SrcRegs, MachineInstr &OrigPHI)
Insert a PHI instruction with incoming edges SrcRegs that are guaranteed to have the same register cl...
static cl::opt< bool > Aggressive("aggressive-ext-opt", cl::Hidden, cl::desc("Aggressive extension optimization"))
static cl::opt< bool > DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(false), cl::desc("Disable advanced copy optimization"))
Specifiy whether or not the value tracking looks through complex instructions.
static Rewriter * getCopyRewriter(MachineInstr &MI, const TargetInstrInfo &TII)
Get the appropriated Rewriter for MI.
static RegSubRegPair getNewSource(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, RegSubRegPair Def, const PeepholeOptimizer::RewriteMapTy &RewriteMap, bool HandleMultipleSources=true)
Given a Def.Reg and Def.SubReg pair, use RewriteMap to find the new source to use for rewrite.
const SmallVectorImpl< MachineOperand > & Cond
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Virtual Register Rewriter
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &Mask, int64_t &Value) const override
For a comparison instruction, return the source registers in SrcReg and SrcReg2 if having two registe...
bool isLoopHeader(const BlockT *BB) const
Describe properties that are true of each instruction in the target description file.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
virtual void MF_HandleChangeDesc(MachineInstr &MI, const MCInstrDesc &TID)
Callback before changing MCInstrDesc.
virtual void MF_HandleRemoval(MachineInstr &MI)=0
Callback before a removal. This should not modify the MI directly.
virtual void MF_HandleInsertion(MachineInstr &MI)=0
Callback after an insertion. This should not modify the MI directly.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
void setDelegate(Delegate *delegate)
Set the delegate.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
MachineBasicBlock * getMBB() const
void setReg(Register Reg)
Change the register this operand corresponds to.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
const uint32_t * getRegMask() const
getRegMask - Returns a bit mask of registers preserved by this RegMask operand.
reg_begin/reg_end - Provide iteration support to walk over all definitions and uses of a register wit...
unsigned getOperandNo() const
getOperandNo - Return the operand # of this MachineOperand in its MachineInstr.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
static const unsigned CommuteAnyOperandIndex
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
char & PeepholeOptimizerID
PeepholeOptimizer - This pass performs peephole optimizations - like extension and comparison elimina...
void initializePeepholeOptimizerPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Implement std::hash so that hash_code can be used in STL containers.
A pair composed of a pair of a register and a sub-register index, and another sub-register index.
A pair composed of a register and a sub-register index.