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;
181 .
set(MachineFunctionProperties::Property::IsSSA);
201 bool findNextSource(
RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap);
211 bool findTargetRecurrence(
Register Reg,
213 RecurrenceCycle &RC);
231 bool foldRedundantNAPhysCopy(
243 (
MI.isRegSequence() ||
MI.isInsertSubreg() ||
244 MI.isExtractSubreg()));
250 return MI.isBitcast() ||
252 (
MI.isRegSequenceLike() ||
MI.isInsertSubregLike() ||
253 MI.isExtractSubregLike()));
266 class RecurrenceInstr {
268 using IndexPair = std::pair<unsigned, unsigned>;
271 RecurrenceInstr(
MachineInstr *MI,
unsigned Idx1,
unsigned Idx2)
272 :
MI(
MI), CommutePair(
std::make_pair(Idx1, Idx2)) {}
275 std::optional<IndexPair> getCommutePair()
const {
return CommutePair; }
279 std::optional<IndexPair> CommutePair;
285 class ValueTrackerResult {
294 ValueTrackerResult() =
default;
300 bool isValid()
const {
return getNumSources() > 0; }
310 void addSource(
Register SrcReg,
unsigned SrcSubReg) {
314 void setSource(
int Idx,
Register SrcReg,
unsigned SrcSubReg) {
315 assert(
Idx < getNumSources() &&
"Reg pair source out of index");
319 int getNumSources()
const {
return RegSrcs.
size(); }
326 assert(
Idx < getNumSources() &&
"Reg source out of index");
327 return RegSrcs[
Idx].Reg;
330 unsigned getSrcSubReg(
int Idx)
const {
331 assert(
Idx < getNumSources() &&
"SubReg source out of index");
332 return RegSrcs[
Idx].SubReg;
336 if (
Other.getInst() != getInst())
339 if (
Other.getNumSources() != getNumSources())
342 for (
int i = 0, e =
Other.getNumSources(); i != e; ++i)
343 if (
Other.getSrcReg(i) != getSrcReg(i) ||
344 Other.getSrcSubReg(i) != getSrcSubReg(i))
387 ValueTrackerResult getNextSourceImpl();
390 ValueTrackerResult getNextSourceFromCopy();
393 ValueTrackerResult getNextSourceFromBitcast();
396 ValueTrackerResult getNextSourceFromRegSequence();
399 ValueTrackerResult getNextSourceFromInsertSubreg();
402 ValueTrackerResult getNextSourceFromExtractSubreg();
405 ValueTrackerResult getNextSourceFromSubregToReg();
408 ValueTrackerResult getNextSourceFromPHI();
420 ValueTracker(
Register Reg,
unsigned DefSubReg,
424 if (!
Reg.isPhysical()) {
425 Def =
MRI.getVRegDef(Reg);
426 DefIdx =
MRI.def_begin(Reg).getOperandNo();
435 ValueTrackerResult getNextSource();
440char PeepholeOptimizer::ID = 0;
445 "Peephole Optimizations",
false,
false)
459bool PeepholeOptimizer::
464 if (!
TII->isCoalescableExtInstr(
MI, SrcReg, DstReg, SubIdx))
470 if (
MRI->hasOneNonDBGUse(SrcReg))
477 DstRC =
TRI->getSubClassWithSubReg(DstRC, SubIdx);
487 TRI->getSubClassWithSubReg(
MRI->getRegClass(SrcReg), SubIdx) !=
nullptr;
493 ReachedBBs.
insert(UI.getParent());
501 bool ExtendLife =
true;
513 if (UseSrcSubIdx && UseMO.getSubReg() != SubIdx)
537 if (UseMBB == &
MBB) {
539 if (!LocalMIs.count(
UseMI))
540 Uses.push_back(&UseMO);
541 }
else if (ReachedBBs.
count(UseMBB)) {
544 Uses.push_back(&UseMO);
557 if (ExtendLife && !ExtendedUses.
empty())
562 bool Changed =
false;
571 PHIBBs.
insert(UI.getParent());
574 for (
unsigned i = 0, e =
Uses.size(); i != e; ++i) {
578 if (PHIBBs.
count(UseMBB))
583 MRI->clearKillFlags(DstReg);
584 MRI->constrainRegClass(DstReg, DstRC);
606 TII->get(TargetOpcode::COPY), NewVR)
607 .
addReg(DstReg, 0, SubIdx);
628 int64_t CmpMask, CmpValue;
635 if (
TII->optimizeCompareInstr(
MI, SrcReg, SrcReg2, CmpMask, CmpValue,
MRI)) {
648 unsigned FalseOp = 0;
649 bool Optimizable =
false;
651 if (
TII->analyzeSelect(
MI,
Cond, TrueOp, FalseOp, Optimizable))
655 if (!
TII->optimizeSelect(
MI, LocalMIs))
658 MI.eraseFromParent();
665 return TII->optimizeCondBranch(
MI);
679bool PeepholeOptimizer::findNextSource(
RegSubRegPair RegSubReg,
680 RewriteMapTy &RewriteMap) {
686 if (
Reg.isPhysical())
694 unsigned PHICount = 0;
706 ValueTrackerResult Res = ValTracker.getNextSource();
712 ValueTrackerResult CurSrcRes = RewriteMap.lookup(CurSrcPair);
713 if (CurSrcRes.isValid()) {
714 assert(CurSrcRes == Res &&
"ValueTrackerResult found must match");
717 if (CurSrcRes.getNumSources() > 1) {
719 <<
"findNextSource: found PHI cycle, aborting...\n");
724 RewriteMap.insert(std::make_pair(CurSrcPair, Res));
728 unsigned NumSrcs = Res.getNumSources();
736 for (
unsigned i = 0; i < NumSrcs; ++i)
741 CurSrcPair = Res.getSrc(0);
751 if (!
TRI->shouldRewriteCopySrc(DefRC, RegSubReg.
SubReg, SrcRC,
757 if (PHICount > 0 && CurSrcPair.
SubReg != 0)
763 }
while (!SrcToLook.
empty());
766 return CurSrcPair.
Reg !=
Reg;
778 assert(!SrcRegs.
empty() &&
"No sources to create a PHI instruction?");
783 assert(SrcRegs[0].
SubReg == 0 &&
"should not have subreg operand");
787 TII.get(TargetOpcode::PHI), NewVR);
789 unsigned MBBOpIdx = 2;
791 MIB.
addReg(RegPair.Reg, 0, RegPair.SubReg);
796 MRI.clearKillFlags(RegPair.Reg);
809 unsigned CurrentSrcIdx = 0;
812 virtual ~Rewriter() =
default;
844 virtual bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg) = 0;
848class CopyRewriter :
public Rewriter {
851 assert(
MI.isCopy() &&
"Expected copy instruction");
853 virtual ~CopyRewriter() =
default;
858 if (CurrentSrcIdx > 0)
872 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
873 if (CurrentSrcIdx != 1)
884class UncoalescableRewriter :
public Rewriter {
889 NumDefs =
MI.getDesc().getNumDefs();
899 if (CurrentSrcIdx == NumDefs)
902 while (CopyLike.getOperand(CurrentSrcIdx).isDead()) {
904 if (CurrentSrcIdx == NumDefs)
917 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
923class InsertSubregRewriter :
public Rewriter {
926 assert(
MI.isInsertSubreg() &&
"Invalid instruction");
943 if (CurrentSrcIdx == 2)
957 (
unsigned)CopyLike.getOperand(3).getImm());
961 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
962 if (CurrentSrcIdx != 2)
973class ExtractSubregRewriter :
public Rewriter {
979 assert(
MI.isExtractSubreg() &&
"Invalid instruction");
990 if (CurrentSrcIdx == 1)
1000 CopyLike.getOperand(2).getImm());
1008 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
1010 if (CurrentSrcIdx != 1)
1013 CopyLike.getOperand(CurrentSrcIdx).setReg(NewReg);
1024 CopyLike.removeOperand(2);
1026 CopyLike.setDesc(
TII.get(TargetOpcode::COPY));
1029 CopyLike.getOperand(CurrentSrcIdx + 1).setImm(NewSubReg);
1035class RegSequenceRewriter :
public Rewriter {
1038 assert(
MI.isRegSequence() &&
"Invalid instruction");
1062 if (CurrentSrcIdx == 0) {
1067 if (CurrentSrcIdx >= CopyLike.getNumOperands())
1070 const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx);
1071 Src.Reg = MOInsertedReg.
getReg();
1073 if ((Src.SubReg = MOInsertedReg.
getSubReg()))
1078 Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm();
1081 Dst.Reg = MODef.
getReg();
1086 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
1089 if ((CurrentSrcIdx & 1) != 1 || CurrentSrcIdx > CopyLike.getNumOperands())
1106 if (
MI.isBitcast() ||
MI.isRegSequenceLike() ||
MI.isInsertSubregLike() ||
1107 MI.isExtractSubregLike())
1108 return new UncoalescableRewriter(
MI);
1110 switch (
MI.getOpcode()) {
1113 case TargetOpcode::COPY:
1114 return new CopyRewriter(
MI);
1115 case TargetOpcode::INSERT_SUBREG:
1116 return new InsertSubregRewriter(
MI);
1117 case TargetOpcode::EXTRACT_SUBREG:
1118 return new ExtractSubregRewriter(
MI,
TII);
1119 case TargetOpcode::REG_SEQUENCE:
1120 return new RegSequenceRewriter(
MI);
1134 bool HandleMultipleSources =
true) {
1137 ValueTrackerResult Res = RewriteMap.
lookup(LookupSrc);
1143 unsigned NumSrcs = Res.getNumSources();
1145 LookupSrc.
Reg = Res.getSrcReg(0);
1146 LookupSrc.
SubReg = Res.getSrcSubReg(0);
1151 if (!HandleMultipleSources)
1157 for (
unsigned i = 0; i < NumSrcs; ++i) {
1158 RegSubRegPair PHISrc(Res.getSrcReg(i), Res.getSrcSubReg(i));
1187bool PeepholeOptimizer::optimizeCoalescableCopy(
MachineInstr &
MI) {
1188 assert(isCoalescableCopy(
MI) &&
"Invalid argument");
1189 assert(
MI.getDesc().getNumDefs() == 1 &&
1190 "Coalescer can understand multiple defs?!");
1196 bool Changed =
false;
1205 while (CpyRewriter->getNextRewritableSource(Src, TrackPair)) {
1207 RewriteMapTy RewriteMap;
1210 if (!findNextSource(TrackPair, RewriteMap))
1217 if (Src.Reg == NewSrc.
Reg || NewSrc.
Reg == 0)
1221 if (CpyRewriter->RewriteCurrentSource(NewSrc.
Reg, NewSrc.
SubReg)) {
1223 MRI->clearKillFlags(NewSrc.
Reg);
1232 NumRewrittenCopies += Changed;
1242PeepholeOptimizer::rewriteSource(
MachineInstr &CopyLike,
1244 assert(!
Def.Reg.isPhysical() &&
"We do not rewrite physical registers");
1251 Register NewVReg =
MRI->createVirtualRegister(DefRC);
1255 TII->get(TargetOpcode::COPY), NewVReg)
1266 MRI->replaceRegWith(
Def.Reg, NewVReg);
1267 MRI->clearKillFlags(NewVReg);
1271 MRI->clearKillFlags(NewSrc.
Reg);
1287bool PeepholeOptimizer::optimizeUncoalescableCopy(
1289 assert(isUncoalescableCopy(
MI) &&
"Invalid argument");
1290 UncoalescableRewriter CpyRewriter(
MI);
1295 RewriteMapTy RewriteMap;
1299 while (CpyRewriter.getNextRewritableSource(Src, Def)) {
1302 if (
Def.Reg.isPhysical())
1307 if (!findNextSource(Def, RewriteMap))
1317 LocalMIs.
insert(&NewCopy);
1322 MI.eraseFromParent();
1323 ++NumUncoalescableCopies;
1330bool PeepholeOptimizer::isLoadFoldable(
1332 if (!
MI.canFoldAsLoad() || !
MI.mayLoad())
1342 if (
Reg.isVirtual() && !
MI.getOperand(0).getSubReg() &&
1343 MRI->hasOneNonDBGUser(Reg)) {
1344 FoldAsLoadDefCandidates.
insert(Reg);
1350bool PeepholeOptimizer::isMoveImmediate(
1354 if (!
MI.isMoveImmediate())
1359 if (
Reg.isVirtual()) {
1360 ImmDefMIs.
insert(std::make_pair(Reg, &
MI));
1371bool PeepholeOptimizer::foldImmediate(
1374 for (
unsigned i = 0, e =
MI.getDesc().getNumOperands(); i != e; ++i) {
1379 if (!
Reg.isVirtual())
1381 if (ImmDefRegs.
count(Reg) == 0)
1384 assert(II != ImmDefMIs.
end() &&
"couldn't find immediate definition");
1385 if (
TII->FoldImmediate(
MI, *II->second, Reg,
MRI)) {
1407bool PeepholeOptimizer::foldRedundantCopy(
1409 assert(
MI.isCopy() &&
"expected a COPY machine instruction");
1412 unsigned SrcSubReg =
MI.getOperand(1).getSubReg();
1413 if (!SrcReg.
isVirtual() && !
MRI->isConstantPhysReg(SrcReg))
1422 if (CopyMIs.
insert(std::make_pair(SrcPair, &
MI)).second) {
1430 "Unexpected mismatching subreg!");
1438 if (
MRI->getRegClass(DstReg) !=
MRI->getRegClass(PrevDstReg))
1441 MRI->replaceRegWith(DstReg, PrevDstReg);
1444 MRI->clearKillFlags(PrevDstReg);
1448bool PeepholeOptimizer::isNAPhysCopy(
Register Reg) {
1449 return Reg.isPhysical() && !
MRI->isAllocatable(Reg);
1452bool PeepholeOptimizer::foldRedundantNAPhysCopy(
1454 assert(
MI.isCopy() &&
"expected a COPY machine instruction");
1461 if (isNAPhysCopy(SrcReg) && DstReg.
isVirtual()) {
1465 NAPhysToVirtMIs.
insert({SrcReg, &
MI});
1469 if (!(SrcReg.
isVirtual() && isNAPhysCopy(DstReg)))
1473 auto PrevCopy = NAPhysToVirtMIs.
find(DstReg);
1474 if (PrevCopy == NAPhysToVirtMIs.
end()) {
1477 LLVM_DEBUG(
dbgs() <<
"NAPhysCopy: intervening clobber forbids erasing "
1483 if (PrevDstReg == SrcReg) {
1496 NAPhysToVirtMIs.
erase(PrevCopy);
1505bool PeepholeOptimizer::findTargetRecurrence(
1507 RecurrenceCycle &RC) {
1509 if (TargetRegs.
count(Reg))
1517 if (!
MRI->hasOneNonDBGUse(Reg))
1525 unsigned Idx =
MI.findRegisterUseOperandIdx(Reg);
1529 if (
MI.getDesc().getNumDefs() != 1)
1539 unsigned TiedUseIdx;
1540 if (!
MI.isRegTiedToUseOperand(0, &TiedUseIdx))
1543 if (
Idx == TiedUseIdx) {
1544 RC.push_back(RecurrenceInstr(&
MI));
1545 return findTargetRecurrence(DefOp.
getReg(), TargetRegs, RC);
1549 if (
TII->findCommutedOpIndices(
MI,
Idx, CommIdx) && CommIdx == TiedUseIdx) {
1550 RC.push_back(RecurrenceInstr(&
MI,
Idx, CommIdx));
1551 return findTargetRecurrence(DefOp.
getReg(), TargetRegs, RC);
1578 for (
unsigned Idx = 1;
Idx <
PHI.getNumOperands();
Idx += 2) {
1584 bool Changed =
false;
1586 if (findTargetRecurrence(
PHI.getOperand(0).getReg(), TargetRegs, RC)) {
1590 for (
auto &RI : RC) {
1592 auto CP = RI.getCommutePair();
1595 TII->commuteInstruction(*(RI.getMI()),
false, (*CP).first,
1609 LLVM_DEBUG(
dbgs() <<
"********** PEEPHOLE OPTIMIZER **********\n");
1618 DT =
Aggressive ? &getAnalysis<MachineDominatorTree>() : nullptr;
1619 MLI = &getAnalysis<MachineLoopInfo>();
1621 bool Changed =
false;
1624 bool SeenMoveImm =
false;
1659 if (
MI->isDebugInstr())
1662 if (
MI->isPosition())
1665 if (IsLoopHeader &&
MI->isPHI()) {
1666 if (optimizeRecurrence(*
MI)) {
1672 if (!
MI->isCopy()) {
1677 if (MO.
isDef() && isNAPhysCopy(Reg)) {
1678 const auto &
Def = NAPhysToVirtMIs.
find(Reg);
1679 if (Def != NAPhysToVirtMIs.
end()) {
1683 <<
"NAPhysCopy: invalidating because of " << *
MI);
1684 NAPhysToVirtMIs.
erase(Def);
1689 for (
auto &RegMI : NAPhysToVirtMIs) {
1693 <<
"NAPhysCopy: invalidating because of " << *
MI);
1694 NAPhysToVirtMIs.erase(Def);
1701 if (
MI->isImplicitDef() ||
MI->isKill())
1704 if (
MI->isInlineAsm() ||
MI->hasUnmodeledSideEffects()) {
1711 NAPhysToVirtMIs.clear();
1714 if ((isUncoalescableCopy(*
MI) &&
1715 optimizeUncoalescableCopy(*
MI, LocalMIs)) ||
1716 (
MI->isCompare() && optimizeCmpInstr(*
MI)) ||
1717 (
MI->isSelect() && optimizeSelect(*
MI, LocalMIs))) {
1724 if (
MI->isConditionalBranch() && optimizeCondBranch(*
MI)) {
1729 if (isCoalescableCopy(*
MI) && optimizeCoalescableCopy(*
MI)) {
1735 if (
MI->isCopy() && (foldRedundantCopy(*
MI, CopySrcMIs) ||
1736 foldRedundantNAPhysCopy(*
MI, NAPhysToVirtMIs))) {
1739 MI->eraseFromParent();
1744 if (isMoveImmediate(*
MI, ImmDefRegs, ImmDefMIs)) {
1747 Changed |= optimizeExtInstr(*
MI,
MBB, LocalMIs);
1754 Changed |= foldImmediate(*
MI, ImmDefRegs, ImmDefMIs);
1760 if (!isLoadFoldable(*
MI, FoldAsLoadDefCandidates) &&
1761 !FoldAsLoadDefCandidates.
empty()) {
1769 for (
unsigned i = MIDesc.
getNumDefs(); i !=
MI->getNumOperands();
1775 if (FoldAsLoadDefCandidates.
count(FoldAsLoadDefReg)) {
1780 Register FoldedReg = FoldAsLoadDefReg;
1783 TII->optimizeLoadInstr(*
MI,
MRI, FoldAsLoadDefReg,
DefMI)) {
1792 if (
MI->shouldUpdateCallSiteInfo())
1793 MI->getMF()->moveCallSiteInfo(
MI, FoldMI);
1794 MI->eraseFromParent();
1796 MRI->markUsesInDebugValueAsUndef(FoldedReg);
1797 FoldAsLoadDefCandidates.
erase(FoldedReg);
1811 if (
MI->isLoadFoldBarrier()) {
1813 FoldAsLoadDefCandidates.
clear();
1821ValueTrackerResult ValueTracker::getNextSourceFromCopy() {
1822 assert(
Def->isCopy() &&
"Invalid definition");
1827 assert(
Def->getNumOperands() -
Def->getNumImplicitOperands() == 2 &&
1828 "Invalid number of operands");
1829 assert(!
Def->hasImplicitDef() &&
"Only implicit uses are allowed");
1831 if (
Def->getOperand(DefIdx).getSubReg() != DefSubReg)
1834 return ValueTrackerResult();
1838 return ValueTrackerResult();
1839 return ValueTrackerResult(Src.getReg(), Src.getSubReg());
1842ValueTrackerResult ValueTracker::getNextSourceFromBitcast() {
1843 assert(
Def->isBitcast() &&
"Invalid definition");
1846 if (
Def->mayRaiseFPException() ||
Def->hasUnmodeledSideEffects())
1847 return ValueTrackerResult();
1850 if (
Def->getDesc().getNumDefs() != 1)
1851 return ValueTrackerResult();
1856 return ValueTrackerResult();
1858 unsigned SrcIdx =
Def->getNumOperands();
1859 for (
unsigned OpIdx = DefIdx + 1, EndOpIdx = SrcIdx; OpIdx != EndOpIdx;
1867 assert(!MO.
isDef() &&
"We should have skipped all the definitions by now");
1868 if (SrcIdx != EndOpIdx)
1870 return ValueTrackerResult();
1876 if (SrcIdx >=
Def->getNumOperands())
1877 return ValueTrackerResult();
1882 if (
UseMI.isSubregToReg())
1883 return ValueTrackerResult();
1888 return ValueTrackerResult();
1889 return ValueTrackerResult(Src.getReg(), Src.getSubReg());
1892ValueTrackerResult ValueTracker::getNextSourceFromRegSequence() {
1893 assert((
Def->isRegSequence() ||
Def->isRegSequenceLike()) &&
1894 "Invalid definition");
1896 if (
Def->getOperand(DefIdx).getSubReg())
1911 return ValueTrackerResult();
1916 return ValueTrackerResult();
1919 if (!
TII->getRegSequenceInputs(*Def, DefIdx, RegSeqInputRegs))
1920 return ValueTrackerResult();
1926 if (RegSeqInput.SubIdx == DefSubReg)
1927 return ValueTrackerResult(RegSeqInput.Reg, RegSeqInput.SubReg);
1933 return ValueTrackerResult();
1936ValueTrackerResult ValueTracker::getNextSourceFromInsertSubreg() {
1937 assert((
Def->isInsertSubreg() ||
Def->isInsertSubregLike()) &&
1938 "Invalid definition");
1940 if (
Def->getOperand(DefIdx).getSubReg())
1944 return ValueTrackerResult();
1949 return ValueTrackerResult();
1953 if (!
TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg))
1954 return ValueTrackerResult();
1963 if (InsertedReg.
SubIdx == DefSubReg) {
1964 return ValueTrackerResult(InsertedReg.
Reg, InsertedReg.
SubReg);
1973 if (
MRI.getRegClass(MODef.
getReg()) !=
MRI.getRegClass(BaseReg.
Reg) ||
1975 return ValueTrackerResult();
1981 !(
TRI->getSubRegIndexLaneMask(DefSubReg) &
1982 TRI->getSubRegIndexLaneMask(InsertedReg.
SubIdx)).none())
1983 return ValueTrackerResult();
1986 return ValueTrackerResult(BaseReg.
Reg, DefSubReg);
1989ValueTrackerResult ValueTracker::getNextSourceFromExtractSubreg() {
1991 Def->isExtractSubregLike()) &&
"Invalid definition");
1998 return ValueTrackerResult();
2003 return ValueTrackerResult();
2006 if (!
TII->getExtractSubregInputs(*Def, DefIdx, ExtractSubregInputReg))
2007 return ValueTrackerResult();
2011 if (ExtractSubregInputReg.
SubReg)
2012 return ValueTrackerResult();
2014 return ValueTrackerResult(ExtractSubregInputReg.
Reg,
2015 ExtractSubregInputReg.
SubIdx);
2018ValueTrackerResult ValueTracker::getNextSourceFromSubregToReg() {
2019 assert(
Def->isSubregToReg() &&
"Invalid definition");
2027 if (DefSubReg !=
Def->getOperand(3).getImm())
2028 return ValueTrackerResult();
2031 if (
Def->getOperand(2).getSubReg())
2032 return ValueTrackerResult();
2034 return ValueTrackerResult(
Def->getOperand(2).getReg(),
2035 Def->getOperand(3).getImm());
2039ValueTrackerResult ValueTracker::getNextSourceFromPHI() {
2040 assert(
Def->isPHI() &&
"Invalid definition");
2041 ValueTrackerResult Res;
2045 if (
Def->getOperand(0).getSubReg() != DefSubReg)
2046 return ValueTrackerResult();
2049 for (
unsigned i = 1, e =
Def->getNumOperands(); i < e; i += 2) {
2055 return ValueTrackerResult();
2062ValueTrackerResult ValueTracker::getNextSourceImpl() {
2063 assert(Def &&
"This method needs a valid definition");
2065 assert(((
Def->getOperand(DefIdx).isDef() &&
2066 (DefIdx < Def->
getDesc().getNumDefs() ||
2067 Def->getDesc().isVariadic())) ||
2068 Def->getOperand(DefIdx).isImplicit()) &&
2071 return getNextSourceFromCopy();
2072 if (
Def->isBitcast())
2073 return getNextSourceFromBitcast();
2077 return ValueTrackerResult();
2078 if (
Def->isRegSequence() ||
Def->isRegSequenceLike())
2079 return getNextSourceFromRegSequence();
2080 if (
Def->isInsertSubreg() ||
Def->isInsertSubregLike())
2081 return getNextSourceFromInsertSubreg();
2082 if (
Def->isExtractSubreg() ||
Def->isExtractSubregLike())
2083 return getNextSourceFromExtractSubreg();
2084 if (
Def->isSubregToReg())
2085 return getNextSourceFromSubregToReg();
2087 return getNextSourceFromPHI();
2088 return ValueTrackerResult();
2091ValueTrackerResult ValueTracker::getNextSource() {
2095 return ValueTrackerResult();
2097 ValueTrackerResult Res = getNextSourceImpl();
2098 if (Res.isValid()) {
2102 bool OneRegSrc = Res.getNumSources() == 1;
2104 Reg = Res.getSrcReg(0);
2111 if (!
Reg.isPhysical() && OneRegSrc) {
2113 if (DI !=
MRI.def_end()) {
2116 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
#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...
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.
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)
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.
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
bool isLoopHeader(const MachineBasicBlock *BB) const
True if the block is a loop header node.
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)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false.
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.