104#define DEBUG_TYPE "peephole-opt"
108 cl::desc(
"Aggressive extension optimization"));
112 cl::desc(
"Disable the peephole optimizer"));
119 cl::desc(
"Disable advanced copy optimization"));
123 cl::desc(
"Disable non-allocatable physical register copy optimization"));
129 cl::desc(
"Limit the length of PHI chains to lookup"));
135 cl::desc(
"Maximum length of recurrence chain when evaluating the benefit "
136 "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");
149class ValueTrackerResult;
150class RecurrenceInstr;
161 : DT(DT), MLI(MLI) {}
181 bool findNextSource(
RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap);
192 bool findTargetRecurrence(
Register Reg,
194 RecurrenceCycle &RC);
223 return MI.isCopy() ||
225 MI.isExtractSubreg()));
232 MI.isInsertSubregLike() ||
233 MI.isExtractSubregLike()));
237 RewriteMapTy &RewriteMap);
251 unsigned SrcSubReg =
MI.getOperand(1).getSubReg();
252 if (!SrcReg.
isVirtual() && !
MRI->isConstantPhysReg(SrcReg))
263 if (!getCopySrc(
MI, SrcPair))
266 auto It = CopySrcMIs.
find(SrcPair);
267 if (It != CopySrcMIs.
end() && It->second == &
MI)
268 CopySrcMIs.
erase(It);
274 deleteChangedCopy(
MI);
301 MachineFunctionProperties::Property::IsSSA);
311class RecurrenceInstr {
313 using IndexPair = std::pair<unsigned, unsigned>;
316 RecurrenceInstr(
MachineInstr *MI,
unsigned Idx1,
unsigned Idx2)
317 :
MI(
MI), CommutePair(
std::make_pair(Idx1, Idx2)) {}
320 std::optional<IndexPair> getCommutePair()
const {
return CommutePair; }
324 std::optional<IndexPair> CommutePair;
330class ValueTrackerResult {
339 ValueTrackerResult() =
default;
343 bool isValid()
const {
return getNumSources() > 0; }
353 void addSource(
Register SrcReg,
unsigned SrcSubReg) {
357 void setSource(
int Idx,
Register SrcReg,
unsigned SrcSubReg) {
358 assert(
Idx < getNumSources() &&
"Reg pair source out of index");
362 int getNumSources()
const {
return RegSrcs.
size(); }
367 assert(
Idx < getNumSources() &&
"Reg source out of index");
368 return RegSrcs[
Idx].Reg;
371 unsigned getSrcSubReg(
int Idx)
const {
372 assert(
Idx < getNumSources() &&
"SubReg source out of index");
373 return RegSrcs[
Idx].SubReg;
377 if (
Other.getInst() != getInst())
380 if (
Other.getNumSources() != getNumSources())
383 for (
int i = 0, e =
Other.getNumSources(); i != e; ++i)
384 if (
Other.getSrcReg(i) != getSrcReg(i) ||
385 Other.getSrcSubReg(i) != getSrcSubReg(i))
428 ValueTrackerResult getNextSourceImpl();
431 ValueTrackerResult getNextSourceFromCopy();
434 ValueTrackerResult getNextSourceFromBitcast();
437 ValueTrackerResult getNextSourceFromRegSequence();
440 ValueTrackerResult getNextSourceFromInsertSubreg();
443 ValueTrackerResult getNextSourceFromExtractSubreg();
446 ValueTrackerResult getNextSourceFromSubregToReg();
449 ValueTrackerResult getNextSourceFromPHI();
464 if (!
Reg.isPhysical()) {
465 Def =
MRI.getVRegDef(Reg);
466 DefIdx =
MRI.def_begin(Reg).getOperandNo();
475 ValueTrackerResult getNextSource();
480char PeepholeOptimizerLegacy::ID = 0;
485 "Peephole Optimizations",
false,
false)
499bool PeepholeOptimizer::optimizeExtInstr(
504 if (!
TII->isCoalescableExtInstr(
MI, SrcReg, DstReg, SubIdx))
510 if (
MRI->hasOneNonDBGUse(SrcReg))
517 DstRC =
TRI->getSubClassWithSubReg(DstRC, SubIdx);
527 TRI->getSubClassWithSubReg(
MRI->getRegClass(SrcReg), SubIdx) !=
nullptr;
533 ReachedBBs.
insert(UI.getParent());
541 bool ExtendLife =
true;
553 if (UseSrcSubIdx && UseMO.getSubReg() != SubIdx)
577 if (UseMBB == &
MBB) {
579 if (!LocalMIs.count(
UseMI))
580 Uses.push_back(&UseMO);
581 }
else if (ReachedBBs.
count(UseMBB)) {
584 Uses.push_back(&UseMO);
597 if (ExtendLife && !ExtendedUses.
empty())
602 bool Changed =
false;
611 PHIBBs.
insert(UI.getParent());
617 if (PHIBBs.
count(UseMBB))
622 MRI->clearKillFlags(DstReg);
623 MRI->constrainRegClass(DstReg, DstRC);
645 TII->get(TargetOpcode::COPY), NewVR)
646 .
addReg(DstReg, 0, SubIdx);
650 UseMO->setReg(NewVR);
667 int64_t CmpMask, CmpValue;
674 if (
TII->optimizeCompareInstr(
MI, SrcReg, SrcReg2, CmpMask, CmpValue,
MRI)) {
684bool PeepholeOptimizer::optimizeSelect(
687 unsigned FalseOp = 0;
688 bool Optimizable =
false;
690 if (
TII->analyzeSelect(
MI,
Cond, TrueOp, FalseOp, Optimizable))
694 if (!
TII->optimizeSelect(
MI, LocalMIs))
697 MI.eraseFromParent();
704 return TII->optimizeCondBranch(
MI);
718bool PeepholeOptimizer::findNextSource(
RegSubRegPair RegSubReg,
719 RewriteMapTy &RewriteMap) {
725 if (
Reg.isPhysical())
733 unsigned PHICount = 0;
745 ValueTrackerResult Res = ValTracker.getNextSource();
751 ValueTrackerResult CurSrcRes = RewriteMap.lookup(CurSrcPair);
752 if (CurSrcRes.isValid()) {
753 assert(CurSrcRes == Res &&
"ValueTrackerResult found must match");
756 if (CurSrcRes.getNumSources() > 1) {
758 <<
"findNextSource: found PHI cycle, aborting...\n");
763 RewriteMap.insert(std::make_pair(CurSrcPair, Res));
767 unsigned NumSrcs = Res.getNumSources();
775 for (
unsigned i = 0; i < NumSrcs; ++i)
780 CurSrcPair = Res.getSrc(0);
790 if (!
TRI->shouldRewriteCopySrc(DefRC, RegSubReg.
SubReg, SrcRC,
796 if (PHICount > 0 && CurSrcPair.
SubReg != 0)
802 }
while (!SrcToLook.
empty());
805 return CurSrcPair.
Reg !=
Reg;
817 assert(!SrcRegs.
empty() &&
"No sources to create a PHI instruction?");
822 assert(SrcRegs[0].
SubReg == 0 &&
"should not have subreg operand");
826 TII.get(TargetOpcode::PHI), NewVR);
828 unsigned MBBOpIdx = 2;
830 MIB.
addReg(RegPair.Reg, 0, RegPair.SubReg);
835 MRI.clearKillFlags(RegPair.Reg);
848 unsigned CurrentSrcIdx = 0;
851 virtual ~Rewriter() =
default;
883 virtual bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg) = 0;
887class CopyRewriter :
public Rewriter {
890 assert(
MI.isCopy() &&
"Expected copy instruction");
892 virtual ~CopyRewriter() =
default;
897 if (CurrentSrcIdx > 0)
911 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
912 if (CurrentSrcIdx != 1)
923class UncoalescableRewriter :
public Rewriter {
928 NumDefs =
MI.getDesc().getNumDefs();
938 if (CurrentSrcIdx == NumDefs)
941 while (CopyLike.getOperand(CurrentSrcIdx).isDead()) {
943 if (CurrentSrcIdx == NumDefs)
956 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
962class InsertSubregRewriter :
public Rewriter {
965 assert(
MI.isInsertSubreg() &&
"Invalid instruction");
982 if (CurrentSrcIdx == 2)
996 (
unsigned)CopyLike.getOperand(3).getImm());
1000 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
1001 if (CurrentSrcIdx != 2)
1012class ExtractSubregRewriter :
public Rewriter {
1018 assert(
MI.isExtractSubreg() &&
"Invalid instruction");
1029 if (CurrentSrcIdx == 1)
1047 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
1049 if (CurrentSrcIdx != 1)
1052 CopyLike.getOperand(CurrentSrcIdx).setReg(NewReg);
1063 CopyLike.removeOperand(2);
1065 CopyLike.setDesc(
TII.get(TargetOpcode::COPY));
1068 CopyLike.getOperand(CurrentSrcIdx + 1).setImm(NewSubReg);
1074class RegSequenceRewriter :
public Rewriter {
1077 assert(
MI.isRegSequence() &&
"Invalid instruction");
1101 if (CurrentSrcIdx == 0) {
1106 if (CurrentSrcIdx >= CopyLike.getNumOperands())
1109 const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx);
1110 Src.Reg = MOInsertedReg.
getReg();
1112 if ((Src.SubReg = MOInsertedReg.
getSubReg()))
1117 Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm();
1120 Dst.Reg = MODef.
getReg();
1125 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
1128 if ((CurrentSrcIdx & 1) != 1 || CurrentSrcIdx > CopyLike.getNumOperands())
1145 if (
MI.isBitcast() ||
MI.isRegSequenceLike() ||
MI.isInsertSubregLike() ||
1146 MI.isExtractSubregLike())
1147 return new UncoalescableRewriter(
MI);
1149 switch (
MI.getOpcode()) {
1152 case TargetOpcode::COPY:
1153 return new CopyRewriter(
MI);
1154 case TargetOpcode::INSERT_SUBREG:
1155 return new InsertSubregRewriter(
MI);
1156 case TargetOpcode::EXTRACT_SUBREG:
1157 return new ExtractSubregRewriter(
MI,
TII);
1158 case TargetOpcode::REG_SEQUENCE:
1159 return new RegSequenceRewriter(
MI);
1173 bool HandleMultipleSources =
true) {
1176 ValueTrackerResult Res = RewriteMap.
lookup(LookupSrc);
1182 unsigned NumSrcs = Res.getNumSources();
1184 LookupSrc.
Reg = Res.getSrcReg(0);
1185 LookupSrc.
SubReg = Res.getSrcSubReg(0);
1190 if (!HandleMultipleSources)
1196 for (
unsigned i = 0; i < NumSrcs; ++i) {
1197 RegSubRegPair PHISrc(Res.getSrcReg(i), Res.getSrcSubReg(i));
1226bool PeepholeOptimizer::optimizeCoalescableCopy(
MachineInstr &
MI) {
1227 assert(isCoalescableCopy(
MI) &&
"Invalid argument");
1228 assert(
MI.getDesc().getNumDefs() == 1 &&
1229 "Coalescer can understand multiple defs?!");
1235 bool Changed =
false;
1244 while (CpyRewriter->getNextRewritableSource(Src, TrackPair)) {
1246 RewriteMapTy RewriteMap;
1249 if (!findNextSource(TrackPair, RewriteMap))
1256 if (Src.Reg == NewSrc.
Reg || NewSrc.
Reg == 0)
1260 if (CpyRewriter->RewriteCurrentSource(NewSrc.
Reg, NewSrc.
SubReg)) {
1262 MRI->clearKillFlags(NewSrc.
Reg);
1271 NumRewrittenCopies += Changed;
1282 RewriteMapTy &RewriteMap) {
1283 assert(!
Def.Reg.isPhysical() &&
"We do not rewrite physical registers");
1290 Register NewVReg =
MRI->createVirtualRegister(DefRC);
1294 TII->get(TargetOpcode::COPY), NewVReg)
1305 MRI->replaceRegWith(
Def.Reg, NewVReg);
1306 MRI->clearKillFlags(NewVReg);
1310 MRI->clearKillFlags(NewSrc.
Reg);
1326bool PeepholeOptimizer::optimizeUncoalescableCopy(
1328 assert(isUncoalescableCopy(
MI) &&
"Invalid argument");
1329 UncoalescableRewriter CpyRewriter(
MI);
1334 RewriteMapTy RewriteMap;
1338 while (CpyRewriter.getNextRewritableSource(Src, Def)) {
1341 if (
Def.Reg.isPhysical())
1346 if (!findNextSource(Def, RewriteMap))
1356 LocalMIs.
insert(&NewCopy);
1361 MI.eraseFromParent();
1362 ++NumUncoalescableCopies;
1369bool PeepholeOptimizer::isLoadFoldable(
1371 if (!
MI.canFoldAsLoad() || !
MI.mayLoad())
1381 if (
Reg.isVirtual() && !
MI.getOperand(0).getSubReg() &&
1382 MRI->hasOneNonDBGUser(Reg)) {
1383 FoldAsLoadDefCandidates.
insert(Reg);
1389bool PeepholeOptimizer::isMoveImmediate(
1393 if (MCID.
getNumDefs() != 1 || !
MI.getOperand(0).isReg())
1396 if (!
Reg.isVirtual())
1400 if (!
MI.isMoveImmediate() && !
TII->getConstValDefinedInReg(
MI, Reg, ImmVal))
1403 ImmDefMIs.
insert(std::make_pair(Reg, &
MI));
1411bool PeepholeOptimizer::foldImmediate(
1415 for (
unsigned i = 0, e =
MI.getDesc().getNumOperands(); i != e; ++i) {
1420 if (!
Reg.isVirtual())
1422 if (ImmDefRegs.
count(Reg) == 0)
1425 assert(
II != ImmDefMIs.
end() &&
"couldn't find immediate definition");
1426 if (
TII->foldImmediate(
MI, *
II->second, Reg,
MRI)) {
1431 if (
MRI->getVRegDef(Reg) &&
1435 MRI->getRegClass(DstReg) ==
MRI->getRegClass(Reg)) {
1436 MRI->replaceRegWith(DstReg, Reg);
1437 MI.eraseFromParent();
1462 assert(
MI.isCopy() &&
"expected a COPY machine instruction");
1465 if (!getCopySrc(
MI, SrcPair))
1472 if (CopySrcMIs.
insert(std::make_pair(SrcPair, &
MI)).second) {
1480 "Unexpected mismatching subreg!");
1488 if (
MRI->getRegClass(DstReg) !=
MRI->getRegClass(PrevDstReg))
1491 MRI->replaceRegWith(DstReg, PrevDstReg);
1494 MRI->clearKillFlags(PrevDstReg);
1498bool PeepholeOptimizer::isNAPhysCopy(
Register Reg) {
1499 return Reg.isPhysical() && !
MRI->isAllocatable(Reg);
1502bool PeepholeOptimizer::foldRedundantNAPhysCopy(
1504 assert(
MI.isCopy() &&
"expected a COPY machine instruction");
1511 if (isNAPhysCopy(SrcReg) && DstReg.
isVirtual()) {
1515 NAPhysToVirtMIs.
insert({SrcReg, &
MI});
1519 if (!(SrcReg.
isVirtual() && isNAPhysCopy(DstReg)))
1523 auto PrevCopy = NAPhysToVirtMIs.
find(DstReg);
1524 if (PrevCopy == NAPhysToVirtMIs.
end()) {
1527 LLVM_DEBUG(
dbgs() <<
"NAPhysCopy: intervening clobber forbids erasing "
1533 if (PrevDstReg == SrcReg) {
1546 NAPhysToVirtMIs.
erase(PrevCopy);
1555bool PeepholeOptimizer::findTargetRecurrence(
1557 RecurrenceCycle &RC) {
1559 if (TargetRegs.
count(Reg))
1567 if (!
MRI->hasOneNonDBGUse(Reg))
1575 unsigned Idx =
MI.findRegisterUseOperandIdx(Reg,
nullptr);
1579 if (
MI.getDesc().getNumDefs() != 1)
1589 unsigned TiedUseIdx;
1590 if (!
MI.isRegTiedToUseOperand(0, &TiedUseIdx))
1593 if (
Idx == TiedUseIdx) {
1594 RC.push_back(RecurrenceInstr(&
MI));
1595 return findTargetRecurrence(DefOp.
getReg(), TargetRegs, RC);
1599 if (
TII->findCommutedOpIndices(
MI,
Idx, CommIdx) && CommIdx == TiedUseIdx) {
1600 RC.push_back(RecurrenceInstr(&
MI,
Idx, CommIdx));
1601 return findTargetRecurrence(DefOp.
getReg(), TargetRegs, RC);
1628 for (
unsigned Idx = 1;
Idx <
PHI.getNumOperands();
Idx += 2) {
1634 bool Changed =
false;
1636 if (findTargetRecurrence(
PHI.getOperand(0).getReg(), TargetRegs, RC)) {
1640 for (
auto &RI : RC) {
1642 auto CP = RI.getCommutePair();
1645 TII->commuteInstruction(*(RI.getMI()),
false, (*CP).first,
1662 PeepholeOptimizer Impl(DT, MLI);
1663 bool Changed = Impl.run(MF);
1674bool PeepholeOptimizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
1678 ? &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree()
1680 auto *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1681 PeepholeOptimizer Impl(DT, MLI);
1682 return Impl.run(MF);
1687 LLVM_DEBUG(
dbgs() <<
"********** PEEPHOLE OPTIMIZER **********\n");
1698 bool Changed =
false;
1701 bool SeenMoveImm =
false;
1734 if (
MI->isDebugInstr())
1737 if (
MI->isPosition())
1740 if (IsLoopHeader &&
MI->isPHI()) {
1741 if (optimizeRecurrence(*
MI)) {
1747 if (!
MI->isCopy()) {
1752 if (MO.
isDef() && isNAPhysCopy(Reg)) {
1753 const auto &
Def = NAPhysToVirtMIs.
find(Reg);
1754 if (Def != NAPhysToVirtMIs.
end()) {
1758 <<
"NAPhysCopy: invalidating because of " << *
MI);
1759 NAPhysToVirtMIs.
erase(Def);
1764 for (
auto &RegMI : NAPhysToVirtMIs) {
1768 <<
"NAPhysCopy: invalidating because of " << *
MI);
1769 NAPhysToVirtMIs.erase(Def);
1776 if (
MI->isImplicitDef() ||
MI->isKill())
1779 if (
MI->isInlineAsm() ||
MI->hasUnmodeledSideEffects()) {
1786 NAPhysToVirtMIs.clear();
1789 if ((isUncoalescableCopy(*
MI) &&
1790 optimizeUncoalescableCopy(*
MI, LocalMIs)) ||
1791 (
MI->isCompare() && optimizeCmpInstr(*
MI)) ||
1792 (
MI->isSelect() && optimizeSelect(*
MI, LocalMIs))) {
1799 if (
MI->isConditionalBranch() && optimizeCondBranch(*
MI)) {
1804 if (isCoalescableCopy(*
MI) && optimizeCoalescableCopy(*
MI)) {
1810 if (
MI->isCopy() && (foldRedundantCopy(*
MI) ||
1811 foldRedundantNAPhysCopy(*
MI, NAPhysToVirtMIs))) {
1814 MI->eraseFromParent();
1819 if (isMoveImmediate(*
MI, ImmDefRegs, ImmDefMIs)) {
1822 Changed |= optimizeExtInstr(*
MI,
MBB, LocalMIs);
1830 Changed |= foldImmediate(*
MI, ImmDefRegs, ImmDefMIs,
Deleted);
1841 if (!isLoadFoldable(*
MI, FoldAsLoadDefCandidates) &&
1842 !FoldAsLoadDefCandidates.
empty()) {
1850 for (
unsigned i = MIDesc.
getNumDefs(); i !=
MI->getNumOperands(); ++i) {
1855 if (FoldAsLoadDefCandidates.
count(FoldAsLoadDefReg)) {
1860 Register FoldedReg = FoldAsLoadDefReg;
1863 TII->optimizeLoadInstr(*
MI,
MRI, FoldAsLoadDefReg,
DefMI)) {
1872 if (
MI->shouldUpdateCallSiteInfo())
1873 MI->getMF()->moveCallSiteInfo(
MI, FoldMI);
1874 MI->eraseFromParent();
1876 MRI->markUsesInDebugValueAsUndef(FoldedReg);
1877 FoldAsLoadDefCandidates.
erase(FoldedReg);
1891 if (
MI->isLoadFoldBarrier()) {
1893 FoldAsLoadDefCandidates.
clear();
1898 MF.resetDelegate(
this);
1902ValueTrackerResult ValueTracker::getNextSourceFromCopy() {
1903 assert(
Def->isCopy() &&
"Invalid definition");
1908 assert(
Def->getNumOperands() -
Def->getNumImplicitOperands() == 2 &&
1909 "Invalid number of operands");
1910 assert(!
Def->hasImplicitDef() &&
"Only implicit uses are allowed");
1912 if (
Def->getOperand(DefIdx).getSubReg() != DefSubReg)
1915 return ValueTrackerResult();
1919 return ValueTrackerResult();
1920 return ValueTrackerResult(Src.getReg(), Src.getSubReg());
1923ValueTrackerResult ValueTracker::getNextSourceFromBitcast() {
1924 assert(
Def->isBitcast() &&
"Invalid definition");
1927 if (
Def->mayRaiseFPException() ||
Def->hasUnmodeledSideEffects())
1928 return ValueTrackerResult();
1931 if (
Def->getDesc().getNumDefs() != 1)
1932 return ValueTrackerResult();
1937 return ValueTrackerResult();
1939 unsigned SrcIdx =
Def->getNumOperands();
1940 for (
unsigned OpIdx = DefIdx + 1, EndOpIdx = SrcIdx; OpIdx != EndOpIdx;
1948 assert(!MO.
isDef() &&
"We should have skipped all the definitions by now");
1949 if (SrcIdx != EndOpIdx)
1951 return ValueTrackerResult();
1957 if (SrcIdx >=
Def->getNumOperands())
1958 return ValueTrackerResult();
1963 if (
UseMI.isSubregToReg())
1964 return ValueTrackerResult();
1969 return ValueTrackerResult();
1970 return ValueTrackerResult(Src.getReg(), Src.getSubReg());
1973ValueTrackerResult ValueTracker::getNextSourceFromRegSequence() {
1974 assert((
Def->isRegSequence() ||
Def->isRegSequenceLike()) &&
1975 "Invalid definition");
1977 if (
Def->getOperand(DefIdx).getSubReg())
1992 return ValueTrackerResult();
1997 return ValueTrackerResult();
2000 if (!
TII->getRegSequenceInputs(*Def, DefIdx, RegSeqInputRegs))
2001 return ValueTrackerResult();
2007 if (RegSeqInput.SubIdx == DefSubReg)
2008 return ValueTrackerResult(RegSeqInput.Reg, RegSeqInput.SubReg);
2014 return ValueTrackerResult();
2017ValueTrackerResult ValueTracker::getNextSourceFromInsertSubreg() {
2018 assert((
Def->isInsertSubreg() ||
Def->isInsertSubregLike()) &&
2019 "Invalid definition");
2021 if (
Def->getOperand(DefIdx).getSubReg())
2025 return ValueTrackerResult();
2030 return ValueTrackerResult();
2034 if (!
TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg))
2035 return ValueTrackerResult();
2044 if (InsertedReg.
SubIdx == DefSubReg) {
2045 return ValueTrackerResult(InsertedReg.
Reg, InsertedReg.
SubReg);
2054 if (
MRI.getRegClass(MODef.
getReg()) !=
MRI.getRegClass(BaseReg.
Reg) ||
2056 return ValueTrackerResult();
2061 if (!
TRI || !(
TRI->getSubRegIndexLaneMask(DefSubReg) &
2062 TRI->getSubRegIndexLaneMask(InsertedReg.
SubIdx))
2064 return ValueTrackerResult();
2067 return ValueTrackerResult(BaseReg.
Reg, DefSubReg);
2070ValueTrackerResult ValueTracker::getNextSourceFromExtractSubreg() {
2071 assert((
Def->isExtractSubreg() ||
Def->isExtractSubregLike()) &&
2072 "Invalid definition");
2079 return ValueTrackerResult();
2084 return ValueTrackerResult();
2087 if (!
TII->getExtractSubregInputs(*Def, DefIdx, ExtractSubregInputReg))
2088 return ValueTrackerResult();
2092 if (ExtractSubregInputReg.
SubReg)
2093 return ValueTrackerResult();
2095 return ValueTrackerResult(ExtractSubregInputReg.
Reg,
2096 ExtractSubregInputReg.
SubIdx);
2099ValueTrackerResult ValueTracker::getNextSourceFromSubregToReg() {
2100 assert(
Def->isSubregToReg() &&
"Invalid definition");
2108 if (DefSubReg !=
Def->getOperand(3).getImm())
2109 return ValueTrackerResult();
2112 if (
Def->getOperand(2).getSubReg())
2113 return ValueTrackerResult();
2115 return ValueTrackerResult(
Def->getOperand(2).getReg(),
2116 Def->getOperand(3).getImm());
2120ValueTrackerResult ValueTracker::getNextSourceFromPHI() {
2121 assert(
Def->isPHI() &&
"Invalid definition");
2122 ValueTrackerResult Res;
2126 if (
Def->getOperand(0).getSubReg() != DefSubReg)
2127 return ValueTrackerResult();
2130 for (
unsigned i = 1, e =
Def->getNumOperands(); i < e; i += 2) {
2136 return ValueTrackerResult();
2143ValueTrackerResult ValueTracker::getNextSourceImpl() {
2144 assert(Def &&
"This method needs a valid definition");
2146 assert(((
Def->getOperand(DefIdx).isDef() &&
2147 (DefIdx < Def->
getDesc().getNumDefs() ||
2148 Def->getDesc().isVariadic())) ||
2149 Def->getOperand(DefIdx).isImplicit()) &&
2152 return getNextSourceFromCopy();
2153 if (
Def->isBitcast())
2154 return getNextSourceFromBitcast();
2158 return ValueTrackerResult();
2159 if (
Def->isRegSequence() ||
Def->isRegSequenceLike())
2160 return getNextSourceFromRegSequence();
2161 if (
Def->isInsertSubreg() ||
Def->isInsertSubregLike())
2162 return getNextSourceFromInsertSubreg();
2163 if (
Def->isExtractSubreg() ||
Def->isExtractSubregLike())
2164 return getNextSourceFromExtractSubreg();
2165 if (
Def->isSubregToReg())
2166 return getNextSourceFromSubregToReg();
2168 return getNextSourceFromPHI();
2169 return ValueTrackerResult();
2172ValueTrackerResult ValueTracker::getNextSource() {
2176 return ValueTrackerResult();
2178 ValueTrackerResult Res = getNextSourceImpl();
2179 if (Res.isValid()) {
2183 bool OneRegSrc = Res.getNumSources() == 1;
2185 Reg = Res.getSrcReg(0);
2192 if (!
Reg.isPhysical() && OneRegSrc) {
2194 if (DI !=
MRI.def_end()) {
2197 DefSubReg = Res.getSrcSubReg(0);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
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
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
Remove Loads Into Fake Uses
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
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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:
Represents analyses that only rely on functions' control flow.
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 dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
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.
An RAII based helper class to modify MachineFunctionProperties when running pass.
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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
Analysis pass that exposes the MachineLoopInfo for a machine function.
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...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
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.
std::pair< unsigned, unsigned > IndexPair
The pair of an instruction index and a operand index.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
char & PeepholeOptimizerLegacyID
PeepholeOptimizer - This pass performs peephole optimizations - like extension and comparison elimina...
PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void initializePeepholeOptimizerLegacyPass(PassRegistry &)
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.