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;
156 int CurrentSrcIdx = 0;
159 virtual ~Rewriter() =
default;
191 virtual bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg) = 0;
195class CopyRewriter :
public Rewriter {
198 assert(
MI.isCopy() &&
"Expected copy instruction");
200 ~CopyRewriter()
override =
default;
204 if (++CurrentSrcIdx > 1)
208 const MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx);
211 const MachineOperand &MODef = CopyLike.getOperand(0);
216 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
217 MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx);
226class UncoalescableRewriter :
public Rewriter {
230 UncoalescableRewriter(MachineInstr &
MI) :
Rewriter(
MI) {
231 NumDefs =
MI.getDesc().getNumDefs();
241 if (CurrentSrcIdx == NumDefs)
244 while (CopyLike.getOperand(CurrentSrcIdx).isDead()) {
246 if (CurrentSrcIdx == NumDefs)
252 const MachineOperand &MODef = CopyLike.getOperand(CurrentSrcIdx);
259 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
265class InsertSubregRewriter :
public Rewriter {
268 assert(
MI.isInsertSubreg() &&
"Invalid instruction");
285 if (CurrentSrcIdx == 2)
289 const MachineOperand &MOInsertedReg = CopyLike.getOperand(2);
291 const MachineOperand &MODef = CopyLike.getOperand(0);
299 (
unsigned)CopyLike.getOperand(3).getImm());
303 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
304 if (CurrentSrcIdx != 2)
307 MachineOperand &MO = CopyLike.getOperand(CurrentSrcIdx);
315class ExtractSubregRewriter :
public Rewriter {
316 const TargetInstrInfo &TII;
319 ExtractSubregRewriter(MachineInstr &
MI,
const TargetInstrInfo &TII)
321 assert(
MI.isExtractSubreg() &&
"Invalid instruction");
332 if (CurrentSrcIdx == 1)
336 const MachineOperand &MOExtractedReg = CopyLike.getOperand(1);
345 const MachineOperand &MODef = CopyLike.getOperand(0);
350 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
352 if (CurrentSrcIdx != 1)
355 CopyLike.getOperand(CurrentSrcIdx).setReg(NewReg);
366 CopyLike.removeOperand(2);
368 CopyLike.setDesc(TII.get(TargetOpcode::COPY));
371 CopyLike.getOperand(CurrentSrcIdx + 1).setImm(NewSubReg);
377class RegSequenceRewriter :
public Rewriter {
380 assert(
MI.isRegSequence() &&
"Invalid instruction");
404 if (
static_cast<unsigned>(CurrentSrcIdx) >= CopyLike.getNumOperands())
407 const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx);
408 Src.Reg = MOInsertedReg.
getReg();
413 Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm();
415 const MachineOperand &MODef = CopyLike.getOperand(0);
417 assert(MODef.
getSubReg() == 0 &&
"cannot have subregister def in SSA");
421 bool RewriteCurrentSource(
Register NewReg,
unsigned NewSubReg)
override {
422 MachineOperand &MO = CopyLike.getOperand(CurrentSrcIdx);
430 const TargetInstrInfo *TII =
nullptr;
431 const TargetRegisterInfo *TRI =
nullptr;
432 MachineRegisterInfo *MRI =
nullptr;
433 MachineDominatorTree *DT =
nullptr;
434 MachineLoopInfo *MLI =
nullptr;
437 PeepholeOptimizer(MachineDominatorTree *DT, MachineLoopInfo *MLI)
438 : DT(DT), MLI(MLI) {}
440 bool run(MachineFunction &MF);
442 using RewriteMapTy = SmallDenseMap<RegSubRegPair, ValueTrackerResult>;
445 using RecurrenceCycle = SmallVector<RecurrenceInstr, 4>;
448 bool optimizeCmpInstr(MachineInstr &
MI, MachineFunction &MF,
449 SmallPtrSet<MachineInstr *, 16> &LocalMIs);
450 bool optimizeExtInstr(MachineInstr &
MI, MachineBasicBlock &
MBB,
451 SmallPtrSetImpl<MachineInstr *> &LocalMIs);
452 bool optimizeSelect(MachineInstr &
MI,
453 SmallPtrSetImpl<MachineInstr *> &LocalMIs);
454 bool optimizeCondBranch(MachineInstr &
MI);
456 bool optimizeCoalescableCopyImpl(
Rewriter &&CpyRewriter);
457 bool optimizeCoalescableCopy(MachineInstr &
MI);
458 bool optimizeUncoalescableCopy(MachineInstr &
MI,
459 SmallPtrSetImpl<MachineInstr *> &LocalMIs);
460 bool optimizeRecurrence(MachineInstr &
PHI);
463 bool isMoveImmediate(MachineInstr &
MI, SmallSet<Register, 4> &ImmDefRegs,
464 DenseMap<Register, MachineInstr *> &ImmDefMIs);
465 bool foldImmediate(MachineInstr &
MI, SmallSet<Register, 4> &ImmDefRegs,
466 DenseMap<Register, MachineInstr *> &ImmDefMIs,
474 const SmallSet<Register, 2> &TargetReg,
475 RecurrenceCycle &RC);
482 bool foldRedundantCopy(MachineInstr &
MI);
493 foldRedundantNAPhysCopy(MachineInstr &
MI,
494 DenseMap<Register, MachineInstr *> &NAPhysToVirtMIs);
496 bool isLoadFoldable(MachineInstr &
MI,
497 SmallSet<Register, 16> &FoldAsLoadDefCandidates);
502 MachineInstr *foldLoadInto(MachineFunction &MF, MachineInstr &
MI,
504 SmallPtrSet<MachineInstr *, 16> &LocalMIs);
508 static bool isCoalescableCopy(
const MachineInstr &
MI) {
511 return MI.isCopy() ||
513 MI.isExtractSubreg()));
518 static bool isUncoalescableCopy(
const MachineInstr &
MI) {
520 MI.isInsertSubregLike() ||
521 MI.isExtractSubregLike()));
524 MachineInstr &rewriteSource(MachineInstr &CopyLike,
RegSubRegPair Def,
525 RewriteMapTy &RewriteMap);
529 DenseMap<RegSubRegPair, MachineInstr *> CopySrcMIs;
532 void MF_HandleInsertion(MachineInstr &
MI)
override {}
539 unsigned SrcSubReg =
MI.getOperand(1).getSubReg();
540 if (!SrcReg.
isVirtual() && !MRI->isConstantPhysReg(SrcReg))
549 void deleteChangedCopy(MachineInstr &
MI) {
551 if (!getCopySrc(
MI, SrcPair))
554 auto It = CopySrcMIs.find(SrcPair);
555 if (It != CopySrcMIs.end() && It->second == &
MI)
556 CopySrcMIs.erase(It);
559 void MF_HandleRemoval(MachineInstr &
MI)
override { deleteChangedCopy(
MI); }
561 void MF_HandleChangeDesc(MachineInstr &
MI,
const MCInstrDesc &TID)
override {
562 deleteChangedCopy(
MI);
570 PeepholeOptimizerLegacy() : MachineFunctionPass(ID) {}
572 bool runOnMachineFunction(MachineFunction &MF)
override;
574 void getAnalysisUsage(AnalysisUsage &AU)
const override {
583 MachineFunctionProperties getRequiredProperties()
const override {
584 return MachineFunctionProperties().setIsSSA();
594class RecurrenceInstr {
596 using IndexPair = std::pair<unsigned, unsigned>;
598 RecurrenceInstr(MachineInstr *MI) : MI(MI) {}
599 RecurrenceInstr(MachineInstr *MI,
unsigned Idx1,
unsigned Idx2)
600 : MI(MI), CommutePair(std::make_pair(Idx1, Idx2)) {}
602 MachineInstr *getMI()
const {
return MI; }
603 std::optional<IndexPair> getCommutePair()
const {
return CommutePair; }
607 std::optional<IndexPair> CommutePair;
613class ValueTrackerResult {
619 const MachineInstr *Inst =
nullptr;
622 ValueTrackerResult() =
default;
624 ValueTrackerResult(
Register Reg,
unsigned SubReg) { addSource(
Reg, SubReg); }
626 bool isValid()
const {
return getNumSources() > 0; }
628 void setInst(
const MachineInstr *
I) { Inst =
I; }
629 const MachineInstr *getInst()
const {
return Inst; }
636 void addSource(
Register SrcReg,
unsigned SrcSubReg) {
640 void setSource(
int Idx,
Register SrcReg,
unsigned SrcSubReg) {
641 assert(Idx < getNumSources() &&
"Reg pair source out of index");
645 int getNumSources()
const {
return RegSrcs.size(); }
650 assert(Idx < getNumSources() &&
"Reg source out of index");
651 return RegSrcs[Idx].Reg;
654 unsigned getSrcSubReg(
int Idx)
const {
655 assert(Idx < getNumSources() &&
"SubReg source out of index");
656 return RegSrcs[Idx].SubReg;
660 if (
Other.getInst() != getInst())
663 if (
Other.getNumSources() != getNumSources())
666 for (
int i = 0, e =
Other.getNumSources(); i != e; ++i)
667 if (
Other.getSrcReg(i) != getSrcReg(i) ||
668 Other.getSrcSubReg(i) != getSrcSubReg(i))
693 const MachineInstr *Def =
nullptr;
705 const MachineRegisterInfo &MRI;
708 const TargetInstrInfo *TII;
711 ValueTrackerResult getNextSourceImpl();
714 ValueTrackerResult getNextSourceFromCopy();
717 ValueTrackerResult getNextSourceFromBitcast();
720 ValueTrackerResult getNextSourceFromRegSequence();
723 ValueTrackerResult getNextSourceFromInsertSubreg();
726 ValueTrackerResult getNextSourceFromExtractSubreg();
729 ValueTrackerResult getNextSourceFromSubregToReg();
732 ValueTrackerResult getNextSourceFromPHI();
744 ValueTracker(
Register Reg,
unsigned DefSubReg,
const MachineRegisterInfo &MRI,
745 const TargetInstrInfo *TII =
nullptr)
746 : DefSubReg(DefSubReg), Reg(Reg), MRI(MRI), TII(TII) {
747 if (!Reg.isPhysical()) {
748 Def = MRI.getVRegDef(Reg);
749 DefIdx = MRI.def_begin(Reg).getOperandNo();
758 ValueTrackerResult getNextSource();
763char PeepholeOptimizerLegacy::ID = 0;
768 "Peephole Optimizations",
false,
false)
782bool PeepholeOptimizer::optimizeExtInstr(
787 if (!
TII->isCoalescableExtInstr(
MI, SrcReg, DstReg, SubIdx))
800 DstRC =
TRI->getSubClassWithSubReg(DstRC, SubIdx);
810 TRI->getSubClassWithSubReg(MRI->
getRegClass(SrcReg), SubIdx) !=
nullptr;
816 ReachedBBs.insert(UI.getParent());
824 bool ExtendLife =
true;
826 MachineInstr *UseMI = UseMO.getParent();
830 if (UseMI->isPHI()) {
836 if (UseSrcSubIdx && UseMO.getSubReg() != SubIdx)
856 if (
UseMI->getOpcode() == TargetOpcode::SUBREG_TO_REG)
860 if (UseMBB == &
MBB) {
862 if (!LocalMIs.count(
UseMI))
863 Uses.push_back(&UseMO);
864 }
else if (ReachedBBs.count(UseMBB)) {
867 Uses.push_back(&UseMO);
871 ExtendedUses.push_back(&UseMO);
880 if (ExtendLife && !ExtendedUses.empty())
882 Uses.append(ExtendedUses.begin(), ExtendedUses.end());
887 SmallPtrSet<MachineBasicBlock *, 4> PHIBBs;
892 for (MachineInstr &UI : MRI->use_nodbg_instructions(DstReg))
894 PHIBBs.insert(UI.getParent());
896 const TargetRegisterClass *RC = MRI->getRegClass(SrcReg);
897 for (MachineOperand *UseMO : Uses) {
898 MachineInstr *UseMI = UseMO->getParent();
899 MachineBasicBlock *UseMBB = UseMI->getParent();
900 if (PHIBBs.count(UseMBB))
905 MRI->clearKillFlags(DstReg);
906 MRI->constrainRegClass(DstReg, DstRC);
924 RC = MRI->getRegClass(UseMI->getOperand(0).getReg());
926 Register NewVR = MRI->createVirtualRegister(RC);
927 BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(),
928 TII->get(TargetOpcode::COPY), NewVR)
929 .addReg(DstReg, {}, SubIdx);
933 UseMO->setReg(NewVR);
946bool PeepholeOptimizer::optimizeCmpInstr(
952 int64_t CmpMask, CmpValue;
959 if (!
TII->optimizeCompareInstr(
MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI))
969 MachineInstr *LoadMI = MRI->
getVRegDef(SrcReg);
976 [](
const MachineInstr &
I) { return I.isLoadFoldBarrier(); }))
977 foldLoadInto(MF, *FlagProducer, SrcReg, LocalMIs);
984bool PeepholeOptimizer::optimizeSelect(
985 MachineInstr &
MI, SmallPtrSetImpl<MachineInstr *> &LocalMIs) {
986 assert(
MI.isSelect() &&
"Should only be called when MI->isSelect() is true");
987 if (!
TII->optimizeSelect(
MI, LocalMIs))
990 MI.eraseFromParent();
996bool PeepholeOptimizer::optimizeCondBranch(MachineInstr &
MI) {
997 return TII->optimizeCondBranch(
MI);
1016 RewriteMapTy &RewriteMap) {
1025 unsigned PHICount = 0;
1032 ValueTracker ValTracker(CurSrcPair.
Reg, CurSrcPair.
SubReg, *MRI,
TII);
1037 ValueTrackerResult Res = ValTracker.getNextSource();
1043 auto [InsertPt, WasInserted] = RewriteMap.try_emplace(CurSrcPair, Res);
1046 const ValueTrackerResult &CurSrcRes = InsertPt->second;
1048 assert(CurSrcRes == Res &&
"ValueTrackerResult found must match");
1051 if (CurSrcRes.getNumSources() > 1) {
1053 <<
"findNextSource: found PHI cycle, aborting...\n");
1061 unsigned NumSrcs = Res.getNumSources();
1069 for (
unsigned i = 0; i < NumSrcs; ++i)
1074 CurSrcPair = Res.getSrc(0);
1084 if (!
TRI->shouldRewriteCopySrc(DefRC, DefSubReg, SrcRC,
1090 if (PHICount > 0 && CurSrcPair.
SubReg != 0)
1096 }
while (!SrcToLook.
empty());
1099 return CurSrcPair.
Reg !=
Reg;
1111 assert(!SrcRegs.
empty() &&
"No sources to create a PHI instruction?");
1116 assert(SrcRegs[0].SubReg == 0 &&
"should not have subreg operand");
1120 TII.get(TargetOpcode::PHI), NewVR);
1122 unsigned MBBOpIdx = 2;
1124 MIB.
addReg(RegPair.Reg, {}, RegPair.SubReg);
1145 const PeepholeOptimizer::RewriteMapTy &RewriteMap,
1146 bool HandleMultipleSources =
true) {
1149 ValueTrackerResult Res = RewriteMap.
lookup(LookupSrc);
1155 unsigned NumSrcs = Res.getNumSources();
1157 LookupSrc.
Reg = Res.getSrcReg(0);
1158 LookupSrc.
SubReg = Res.getSrcSubReg(0);
1163 if (!HandleMultipleSources)
1169 for (
unsigned i = 0; i < NumSrcs; ++i) {
1170 RegSubRegPair PHISrc(Res.getSrcReg(i), Res.getSrcSubReg(i));
1188bool PeepholeOptimizer::optimizeCoalescableCopyImpl(
Rewriter &&CpyRewriter) {
1194 while (CpyRewriter.getNextRewritableSource(TrackPair, Dst)) {
1195 if (Dst.Reg.isPhysical()) {
1206 RewriteMapTy RewriteMap;
1209 if (!findNextSource(DefRC, Dst.SubReg, TrackPair, RewriteMap))
1217 "should not rewrite source to original value");
1227 TRI->getSubClassWithSubReg(RC, NewSrc.
SubReg);
1234 if (CpyRewriter.RewriteCurrentSource(NewSrc.
Reg, NewSrc.
SubReg)) {
1246 NumRewrittenCopies +=
Changed;
1261bool PeepholeOptimizer::optimizeCoalescableCopy(MachineInstr &
MI) {
1262 assert(isCoalescableCopy(
MI) &&
"Invalid argument");
1263 assert(
MI.getDesc().getNumDefs() == 1 &&
1264 "Coalescer can understand multiple defs?!");
1265 const MachineOperand &MODef =
MI.getOperand(0);
1270 switch (
MI.getOpcode()) {
1271 case TargetOpcode::COPY:
1272 return optimizeCoalescableCopyImpl(CopyRewriter(
MI));
1273 case TargetOpcode::INSERT_SUBREG:
1274 return optimizeCoalescableCopyImpl(InsertSubregRewriter(
MI));
1275 case TargetOpcode::EXTRACT_SUBREG:
1276 return optimizeCoalescableCopyImpl(ExtractSubregRewriter(
MI, *
TII));
1277 case TargetOpcode::REG_SEQUENCE:
1278 return optimizeCoalescableCopyImpl(RegSequenceRewriter(
MI));
1281 if (
MI.isBitcast() ||
MI.isRegSequenceLike() ||
MI.isInsertSubregLike() ||
1282 MI.isExtractSubregLike())
1283 return optimizeCoalescableCopyImpl(UncoalescableRewriter(
MI));
1293MachineInstr &PeepholeOptimizer::rewriteSource(MachineInstr &CopyLike,
1295 RewriteMapTy &RewriteMap) {
1296 assert(!
Def.Reg.isPhysical() &&
"We do not rewrite physical registers");
1308 TRI->getSubClassWithSubReg(NewSrcRC, NewSrc.
SubReg);
1317 MachineInstr *NewCopy =
1319 TII->get(TargetOpcode::COPY), NewVReg)
1351bool PeepholeOptimizer::optimizeUncoalescableCopy(
1352 MachineInstr &
MI, SmallPtrSetImpl<MachineInstr *> &LocalMIs) {
1353 assert(isUncoalescableCopy(
MI) &&
"Invalid argument");
1354 UncoalescableRewriter CpyRewriter(
MI);
1359 RewriteMapTy RewriteMap;
1363 while (CpyRewriter.getNextRewritableSource(Src, Def)) {
1366 if (
Def.Reg.isPhysical())
1376 if (!findNextSource(DefRC,
Def.SubReg, Def, RewriteMap))
1385 MachineInstr &NewCopy = rewriteSource(
MI, Def, RewriteMap);
1386 LocalMIs.
insert(&NewCopy);
1391 MI.eraseFromParent();
1392 ++NumUncoalescableCopies;
1399bool PeepholeOptimizer::isLoadFoldable(
1400 MachineInstr &
MI, SmallSet<Register, 16> &FoldAsLoadDefCandidates) {
1401 if (!
MI.canFoldAsLoad() || !
MI.mayLoad())
1403 const MCInstrDesc &MCID =
MI.getDesc();
1420PeepholeOptimizer::foldLoadInto(MachineFunction &MF, MachineInstr &
MI,
1422 SmallPtrSet<MachineInstr *, 16> &LocalMIs) {
1424 MachineInstr *
DefMI =
nullptr;
1425 MachineInstr *CopyMI =
nullptr;
1426 MachineInstr *FoldMI =
TII->optimizeLoadInstr(
MI, MRI,
Reg,
DefMI, CopyMI);
1435 if (
MI.shouldUpdateAdditionalCallInfo())
1437 MI.eraseFromParent();
1444bool PeepholeOptimizer::isMoveImmediate(
1445 MachineInstr &
MI, SmallSet<Register, 4> &ImmDefRegs,
1446 DenseMap<Register, MachineInstr *> &ImmDefMIs) {
1447 const MCInstrDesc &MCID =
MI.getDesc();
1448 if (MCID.
getNumDefs() != 1 || !
MI.getOperand(0).isReg())
1455 if (!
MI.isMoveImmediate() && !
TII->getConstValDefinedInReg(
MI,
Reg, ImmVal))
1466bool PeepholeOptimizer::foldImmediate(
1467 MachineInstr &
MI, SmallSet<Register, 4> &ImmDefRegs,
1468 DenseMap<Register, MachineInstr *> &ImmDefMIs,
bool &
Deleted) {
1470 for (
unsigned i = 0, e =
MI.getDesc().getNumOperands(); i != e; ++i) {
1471 MachineOperand &MO =
MI.getOperand(i);
1480 assert(
II != ImmDefMIs.
end() &&
"couldn't find immediate definition");
1481 if (
TII->foldImmediate(
MI, *
II->second,
Reg, MRI)) {
1493 MI.eraseFromParent();
1517bool PeepholeOptimizer::foldRedundantCopy(MachineInstr &
MI) {
1518 assert(
MI.isCopy() &&
"expected a COPY machine instruction");
1521 if (!getCopySrc(
MI, SrcPair))
1528 if (CopySrcMIs.
insert(std::make_pair(SrcPair, &
MI)).second) {
1533 MachineInstr *PrevCopy = CopySrcMIs.
find(SrcPair)->second;
1536 "Unexpected mismatching subreg!");
1554bool PeepholeOptimizer::isNAPhysCopy(
Register Reg) {
1558bool PeepholeOptimizer::foldRedundantNAPhysCopy(
1559 MachineInstr &
MI, DenseMap<Register, MachineInstr *> &NAPhysToVirtMIs) {
1560 assert(
MI.isCopy() &&
"expected a COPY machine instruction");
1567 if (isNAPhysCopy(SrcReg) && DstReg.
isVirtual()) {
1571 NAPhysToVirtMIs.
insert({SrcReg, &
MI});
1575 if (!(SrcReg.
isVirtual() && isNAPhysCopy(DstReg)))
1579 auto PrevCopy = NAPhysToVirtMIs.
find(DstReg);
1580 if (PrevCopy == NAPhysToVirtMIs.
end()) {
1583 LLVM_DEBUG(
dbgs() <<
"NAPhysCopy: intervening clobber forbids erasing "
1589 if (PrevDstReg == SrcReg) {
1602 NAPhysToVirtMIs.
erase(PrevCopy);
1611bool PeepholeOptimizer::findTargetRecurrence(
1612 Register Reg,
const SmallSet<Register, 2> &TargetRegs,
1613 RecurrenceCycle &RC) {
1631 unsigned Idx =
MI.findRegisterUseOperandIdx(
Reg,
nullptr);
1635 if (
MI.getDesc().getNumDefs() != 1)
1638 MachineOperand &DefOp =
MI.getOperand(0);
1645 unsigned TiedUseIdx;
1646 if (!
MI.isRegTiedToUseOperand(0, &TiedUseIdx))
1649 if (Idx == TiedUseIdx) {
1650 RC.push_back(RecurrenceInstr(&
MI));
1651 return findTargetRecurrence(DefOp.
getReg(), TargetRegs, RC);
1655 if (
TII->findCommutedOpIndices(
MI, Idx, CommIdx) && CommIdx == TiedUseIdx) {
1656 RC.push_back(RecurrenceInstr(&
MI, Idx, CommIdx));
1657 return findTargetRecurrence(DefOp.
getReg(), TargetRegs, RC);
1682bool PeepholeOptimizer::optimizeRecurrence(MachineInstr &
PHI) {
1683 SmallSet<Register, 2> TargetRegs;
1684 for (
unsigned Idx = 1; Idx <
PHI.getNumOperands(); Idx += 2) {
1685 MachineOperand &MO =
PHI.getOperand(Idx);
1692 if (findTargetRecurrence(
PHI.getOperand(0).getReg(), TargetRegs, RC)) {
1696 for (
auto &RI : RC) {
1698 auto CP = RI.getCommutePair();
1701 TII->commuteInstruction(*(RI.getMI()),
false, (*CP).first,
1718 PeepholeOptimizer Impl(DT, MLI);
1728bool PeepholeOptimizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
1732 ? &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree()
1734 auto *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1735 PeepholeOptimizer Impl(DT, MLI);
1736 return Impl.run(MF);
1741 LLVM_DEBUG(
dbgs() <<
"********** PEEPHOLE OPTIMIZER **********\n");
1755 bool SeenMoveImm =
false;
1788 if (
MI->isDebugInstr())
1791 if (
MI->isPosition())
1794 if (IsLoopHeader &&
MI->isPHI()) {
1795 if (optimizeRecurrence(*
MI)) {
1801 if (!
MI->isCopy()) {
1802 for (
const MachineOperand &MO :
MI->operands()) {
1806 if (MO.
isDef() && isNAPhysCopy(
Reg)) {
1808 if (Def != NAPhysToVirtMIs.
end()) {
1812 <<
"NAPhysCopy: invalidating because of " << *
MI);
1813 NAPhysToVirtMIs.
erase(Def);
1818 NAPhysToVirtMIs.
remove_if([&](
const auto &RegMI) {
1822 <<
"NAPhysCopy: invalidating because of " << *
MI);
1829 if (
MI->isImplicitDef() ||
MI->isKill())
1832 if (
MI->isInlineAsm() ||
MI->hasUnmodeledSideEffects()) {
1839 NAPhysToVirtMIs.
clear();
1842 if (
MI->isCompare() && optimizeCmpInstr(*
MI, MF, LocalMIs)) {
1848 if ((isUncoalescableCopy(*
MI) &&
1849 optimizeUncoalescableCopy(*
MI, LocalMIs)) ||
1850 (
MI->isSelect() && optimizeSelect(*
MI, LocalMIs))) {
1857 if (
MI->isConditionalBranch() && optimizeCondBranch(*
MI)) {
1862 if (isCoalescableCopy(*
MI) && optimizeCoalescableCopy(*
MI)) {
1868 if (
MI->isCopy() && (foldRedundantCopy(*
MI) ||
1869 foldRedundantNAPhysCopy(*
MI, NAPhysToVirtMIs))) {
1872 MI->eraseFromParent();
1877 if (isMoveImmediate(*
MI, ImmDefRegs, ImmDefMIs)) {
1899 if (!isLoadFoldable(*
MI, FoldAsLoadDefCandidates) &&
1900 !FoldAsLoadDefCandidates.
empty()) {
1907 const MCInstrDesc &MIDesc =
MI->getDesc();
1908 for (
unsigned i = MIDesc.
getNumDefs(); i !=
MI->getNumOperands(); ++i) {
1909 const MachineOperand &MOp =
MI->getOperand(i);
1913 if (FoldAsLoadDefCandidates.
count(FoldAsLoadDefReg)) {
1916 Register FoldedReg = FoldAsLoadDefReg;
1917 if (MachineInstr *FoldMI =
1918 foldLoadInto(MF, *
MI, FoldAsLoadDefReg, LocalMIs)) {
1919 FoldAsLoadDefCandidates.
erase(FoldedReg);
1931 if (
MI->isLoadFoldBarrier()) {
1933 FoldAsLoadDefCandidates.
clear();
1938 MF.resetDelegate(
this);
1942ValueTrackerResult ValueTracker::getNextSourceFromCopy() {
1943 assert(
Def->isCopy() &&
"Invalid definition");
1948 assert(
Def->getNumOperands() -
Def->getNumImplicitOperands() == 2 &&
1949 "Invalid number of operands");
1950 assert(!
Def->hasImplicitDef() &&
"Only implicit uses are allowed");
1951 assert(!
Def->getOperand(DefIdx).getSubReg() &&
"no subregister defs in SSA");
1954 const MachineOperand &Src =
Def->getOperand(1);
1956 return ValueTrackerResult();
1959 unsigned SubReg = Src.getSubReg();
1962 SubReg =
TRI->composeSubRegIndices(SubReg, DefSubReg);
1967 if (!
TRI->isSubRegValidForRegClass(RegRC, SubReg))
1968 return ValueTrackerResult();
1970 if (!
TRI->getSubReg(SrcReg, SubReg))
1971 return ValueTrackerResult();
1975 return ValueTrackerResult(SrcReg, SubReg);
1978ValueTrackerResult ValueTracker::getNextSourceFromBitcast() {
1979 assert(
Def->isBitcast() &&
"Invalid definition");
1982 if (
Def->mayRaiseFPException() ||
Def->hasUnmodeledSideEffects())
1983 return ValueTrackerResult();
1986 if (
Def->getDesc().getNumDefs() != 1)
1987 return ValueTrackerResult();
1989 assert(!
Def->getOperand(DefIdx).getSubReg() &&
"no subregister defs in SSA");
1991 unsigned SrcIdx =
Def->getNumOperands();
1992 for (
unsigned OpIdx = DefIdx + 1, EndOpIdx = SrcIdx;
OpIdx != EndOpIdx;
1994 const MachineOperand &MO =
Def->getOperand(
OpIdx);
2000 assert(!MO.
isDef() &&
"We should have skipped all the definitions by now");
2001 if (SrcIdx != EndOpIdx)
2003 return ValueTrackerResult();
2009 if (SrcIdx >=
Def->getNumOperands())
2010 return ValueTrackerResult();
2012 const MachineOperand &DefOp =
Def->getOperand(DefIdx);
2017 if (
UseMI.isSubregToReg())
2018 return ValueTrackerResult();
2021 const MachineOperand &Src =
Def->getOperand(SrcIdx);
2023 return ValueTrackerResult();
2024 return ValueTrackerResult(Src.getReg(), Src.getSubReg());
2027ValueTrackerResult ValueTracker::getNextSourceFromRegSequence() {
2028 assert((
Def->isRegSequence() ||
Def->isRegSequenceLike()) &&
2029 "Invalid definition");
2031 assert(!
Def->getOperand(DefIdx).getSubReg() &&
"illegal subregister def");
2034 if (!
TII->getRegSequenceInputs(*Def, DefIdx, RegSeqInputRegs))
2035 return ValueTrackerResult();
2043 if (RegSeqInput.SubIdx == DefSubReg)
2044 return ValueTrackerResult(RegSeqInput.Reg, RegSeqInput.SubReg);
2052 LaneBitmask DefMask =
TRI->getSubRegIndexLaneMask(DefSubReg);
2053 LaneBitmask ThisOpRegMask =
TRI->getSubRegIndexLaneMask(RegSeqInput.SubIdx);
2059 if ((DefMask & ThisOpRegMask) != DefMask)
2062 unsigned ReverseDefCompose =
2063 TRI->reverseComposeSubRegIndices(RegSeqInput.SubIdx, DefSubReg);
2064 if (!ReverseDefCompose)
2067 unsigned ComposedDefInSrcReg1 =
2068 TRI->composeSubRegIndices(RegSeqInput.SubReg, ReverseDefCompose);
2075 if (!
TRI->isSubRegValidForRegClass(SrcRC, ComposedDefInSrcReg1))
2076 return ValueTrackerResult();
2078 return ValueTrackerResult(RegSeqInput.Reg, ComposedDefInSrcReg1);
2084 return ValueTrackerResult();
2087ValueTrackerResult ValueTracker::getNextSourceFromInsertSubreg() {
2088 assert((
Def->isInsertSubreg() ||
Def->isInsertSubregLike()) &&
2089 "Invalid definition");
2090 assert(!
Def->getOperand(DefIdx).getSubReg() &&
"no subreg defs in SSA");
2094 if (!
TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg))
2095 return ValueTrackerResult();
2104 if (InsertedReg.
SubIdx == DefSubReg) {
2105 return ValueTrackerResult(InsertedReg.
Reg, InsertedReg.
SubReg);
2110 const MachineOperand &MODef =
Def->getOperand(DefIdx);
2116 return ValueTrackerResult();
2121 if ((
TRI->getSubRegIndexLaneMask(DefSubReg) &
2122 TRI->getSubRegIndexLaneMask(InsertedReg.
SubIdx))
2124 return ValueTrackerResult();
2127 return ValueTrackerResult(
BaseReg.Reg, DefSubReg);
2130ValueTrackerResult ValueTracker::getNextSourceFromExtractSubreg() {
2131 assert((
Def->isExtractSubreg() ||
Def->isExtractSubregLike()) &&
2132 "Invalid definition");
2139 return ValueTrackerResult();
2142 if (!
TII->getExtractSubregInputs(*Def, DefIdx, ExtractSubregInputReg))
2143 return ValueTrackerResult();
2147 if (ExtractSubregInputReg.
SubReg)
2148 return ValueTrackerResult();
2150 return ValueTrackerResult(ExtractSubregInputReg.
Reg,
2151 ExtractSubregInputReg.
SubIdx);
2154ValueTrackerResult ValueTracker::getNextSourceFromSubregToReg() {
2155 assert(
Def->isSubregToReg() &&
"Invalid definition");
2163 if (DefSubReg !=
Def->getOperand(2).getImm())
2164 return ValueTrackerResult();
2167 if (
Def->getOperand(1).getSubReg())
2168 return ValueTrackerResult();
2170 return ValueTrackerResult(
Def->getOperand(1).getReg(),
2171 Def->getOperand(2).getImm());
2175ValueTrackerResult ValueTracker::getNextSourceFromPHI() {
2176 assert(
Def->isPHI() &&
"Invalid definition");
2177 ValueTrackerResult Res;
2180 for (
unsigned i = 1, e =
Def->getNumOperands(); i < e; i += 2) {
2181 const MachineOperand &MO =
Def->getOperand(i);
2186 return ValueTrackerResult();
2193ValueTrackerResult ValueTracker::getNextSourceImpl() {
2194 assert(Def &&
"This method needs a valid definition");
2196 assert(((
Def->getOperand(DefIdx).isDef() &&
2197 (DefIdx < Def->
getDesc().getNumDefs() ||
2198 Def->getDesc().isVariadic())) ||
2199 Def->getOperand(DefIdx).isImplicit()) &&
2202 return getNextSourceFromCopy();
2203 if (
Def->isBitcast())
2204 return getNextSourceFromBitcast();
2208 return ValueTrackerResult();
2209 if (
Def->isRegSequence() ||
Def->isRegSequenceLike())
2210 return getNextSourceFromRegSequence();
2211 if (
Def->isInsertSubreg() ||
Def->isInsertSubregLike())
2212 return getNextSourceFromInsertSubreg();
2213 if (
Def->isExtractSubreg() ||
Def->isExtractSubregLike())
2214 return getNextSourceFromExtractSubreg();
2215 if (
Def->isSubregToReg())
2216 return getNextSourceFromSubregToReg();
2218 return getNextSourceFromPHI();
2219 return ValueTrackerResult();
2222ValueTrackerResult ValueTracker::getNextSource() {
2226 return ValueTrackerResult();
2228 ValueTrackerResult Res = getNextSourceImpl();
2229 if (Res.isValid()) {
2233 bool OneRegSrc = Res.getNumSources() == 1;
2235 Reg = Res.getSrcReg(0);
2247 DefSubReg = Res.getSrcSubReg(0);
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the DenseMap class.
const HexagonInstrInfo * TII
A common definition of LaneBitmask for use in TableGen and CodeGen.
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
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)
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.
TargetInstrInfo::RegSubRegPairAndIdx RegSubRegPairAndIdx
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.
Remove Loads Into Fake Uses
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
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
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
LLVM_ABI 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
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
bool remove_if(Predicate Pred)
Remove entries that match the given predicate.
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
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
An RAII based helper class to modify MachineFunctionProperties when running pass.
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
bool dominates(const MachineInstr *A, const MachineInstr *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.
void moveAdditionalCallInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
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, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool canFoldAsLoad(QueryType Type=IgnoreBundle) const
Return true for instructions that can be folded as memory operands in other instructions.
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
LLVM_ABI 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.
unsigned getOperandNo() const
getOperandNo - Return the operand # of this MachineOperand in its MachineInstr.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
use_nodbg_iterator use_nodbg_begin(Register RegNo) const
LLVM_ABI void markUsesInDebugValueAsUndef(Register Reg) const
markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the specified register as undefined wh...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
def_iterator def_begin(Register RegNo) const
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
LLVM_ABI bool hasOneNonDBGUser(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug instruction using the specified regis...
bool isAllocatable(MCRegister PhysReg) const
isAllocatable - Returns true when PhysReg belongs to an allocatable register class and it hasn't been...
defusechain_iterator< false, true, false, true, false > def_iterator
def_iterator/def_begin/def_end - Walk all defs of the specified register.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
static def_iterator def_end()
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
NodeAddr< DefNode * > Def
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
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.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI char & PeepholeOptimizerLegacyID
PeepholeOptimizer - This pass performs peephole optimizations - like extension and comparison elimina...
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MCRegisterClass TargetRegisterClass
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.