diff options
author | Akshat Oke <Akshat.Oke@amd.com> | 2024-11-18 10:58:48 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-18 10:58:48 +0530 |
commit | 00aa08119aa03ea4722196bc7d0e84a4e2a044c7 (patch) | |
tree | cfb9fdece29abe49a49c7f06ff75bd4f3c72689e /llvm/lib | |
parent | fd3ff2007ab30c74772572798f3e494fdaac7ac2 (diff) | |
download | llvm-00aa08119aa03ea4722196bc7d0e84a4e2a044c7.zip llvm-00aa08119aa03ea4722196bc7d0e84a4e2a044c7.tar.gz llvm-00aa08119aa03ea4722196bc7d0e84a4e2a044c7.tar.bz2 |
[NFC] Clang format PeepholeOptimizer (#116325)
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/PeepholeOptimizer.cpp | 653 |
1 files changed, 320 insertions, 333 deletions
diff --git a/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/llvm/lib/CodeGen/PeepholeOptimizer.cpp index 746ec0f..12b276f 100644 --- a/llvm/lib/CodeGen/PeepholeOptimizer.cpp +++ b/llvm/lib/CodeGen/PeepholeOptimizer.cpp @@ -102,20 +102,19 @@ using RegSubRegPairAndIdx = TargetInstrInfo::RegSubRegPairAndIdx; #define DEBUG_TYPE "peephole-opt" // Optimize Extensions -static cl::opt<bool> -Aggressive("aggressive-ext-opt", cl::Hidden, - cl::desc("Aggressive extension optimization")); +static cl::opt<bool> Aggressive("aggressive-ext-opt", cl::Hidden, + cl::desc("Aggressive extension optimization")); static cl::opt<bool> -DisablePeephole("disable-peephole", cl::Hidden, cl::init(false), - cl::desc("Disable the peephole optimizer")); + DisablePeephole("disable-peephole", cl::Hidden, cl::init(false), + cl::desc("Disable the peephole optimizer")); /// Specifiy whether or not the value tracking looks through /// complex instructions. When this is true, the value tracker /// bails on everything that is not a copy or a bitcast. static cl::opt<bool> -DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(false), - cl::desc("Disable advanced copy optimization")); + DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(false), + cl::desc("Disable advanced copy optimization")); static cl::opt<bool> DisableNAPhysCopyOpt( "disable-non-allocatable-phys-copy-opt", cl::Hidden, cl::init(false), @@ -123,9 +122,9 @@ static cl::opt<bool> DisableNAPhysCopyOpt( // Limit the number of PHI instructions to process // in PeepholeOptimizer::getNextSource. -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<unsigned> + RewritePHILimit("rewrite-phi-limit", cl::Hidden, cl::init(10), + cl::desc("Limit the length of PHI chains to lookup")); // Limit the length of recurrence chain when evaluating the benefit of // commuting operands. @@ -134,7 +133,6 @@ static cl::opt<unsigned> MaxRecurrenceChain( cl::desc("Maximum length of recurrence chain when evaluating the benefit " "of commuting operands")); - STATISTIC(NumReuse, "Number of extension results reused"); STATISTIC(NumCmps, "Number of compares eliminated"); STATISTIC(NumImmFold, "Number of move immediate folded"); @@ -146,338 +144,328 @@ STATISTIC(NumNAPhysCopies, "Number of non-allocatable physical copies removed"); namespace { - class ValueTrackerResult; - class RecurrenceInstr; +class ValueTrackerResult; +class RecurrenceInstr; - class PeepholeOptimizer : public MachineFunctionPass, - private MachineFunction::Delegate { - const TargetInstrInfo *TII = nullptr; - const TargetRegisterInfo *TRI = nullptr; - MachineRegisterInfo *MRI = nullptr; - MachineDominatorTree *DT = nullptr; // Machine dominator tree - MachineLoopInfo *MLI = nullptr; +class PeepholeOptimizer : public MachineFunctionPass, + private MachineFunction::Delegate { + const TargetInstrInfo *TII = nullptr; + const TargetRegisterInfo *TRI = nullptr; + MachineRegisterInfo *MRI = nullptr; + MachineDominatorTree *DT = nullptr; // Machine dominator tree + MachineLoopInfo *MLI = nullptr; - public: - static char ID; // Pass identification +public: + static char ID; // Pass identification - PeepholeOptimizer() : MachineFunctionPass(ID) { - initializePeepholeOptimizerPass(*PassRegistry::getPassRegistry()); - } + PeepholeOptimizer() : MachineFunctionPass(ID) { + initializePeepholeOptimizerPass(*PassRegistry::getPassRegistry()); + } - bool runOnMachineFunction(MachineFunction &MF) override; + bool runOnMachineFunction(MachineFunction &MF) override; - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - MachineFunctionPass::getAnalysisUsage(AU); - AU.addRequired<MachineLoopInfoWrapperPass>(); - AU.addPreserved<MachineLoopInfoWrapperPass>(); - if (Aggressive) { - AU.addRequired<MachineDominatorTreeWrapperPass>(); - AU.addPreserved<MachineDominatorTreeWrapperPass>(); - } + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired<MachineLoopInfoWrapperPass>(); + AU.addPreserved<MachineLoopInfoWrapperPass>(); + if (Aggressive) { + AU.addRequired<MachineDominatorTreeWrapperPass>(); + AU.addPreserved<MachineDominatorTreeWrapperPass>(); } + } - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties() - .set(MachineFunctionProperties::Property::IsSSA); - } + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::IsSSA); + } - /// Track Def -> Use info used for rewriting copies. - using RewriteMapTy = SmallDenseMap<RegSubRegPair, ValueTrackerResult>; + /// Track Def -> Use info used for rewriting copies. + using RewriteMapTy = SmallDenseMap<RegSubRegPair, ValueTrackerResult>; - /// Sequence of instructions that formulate recurrence cycle. - using RecurrenceCycle = SmallVector<RecurrenceInstr, 4>; + /// Sequence of instructions that formulate recurrence cycle. + using RecurrenceCycle = SmallVector<RecurrenceInstr, 4>; - private: - bool optimizeCmpInstr(MachineInstr &MI); - bool optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, - SmallPtrSetImpl<MachineInstr*> &LocalMIs); - bool optimizeSelect(MachineInstr &MI, +private: + bool optimizeCmpInstr(MachineInstr &MI); + bool optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, SmallPtrSetImpl<MachineInstr *> &LocalMIs); - bool optimizeCondBranch(MachineInstr &MI); - bool optimizeCoalescableCopy(MachineInstr &MI); - bool optimizeUncoalescableCopy(MachineInstr &MI, - SmallPtrSetImpl<MachineInstr *> &LocalMIs); - bool optimizeRecurrence(MachineInstr &PHI); - bool findNextSource(RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap); - bool isMoveImmediate(MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs, - DenseMap<Register, MachineInstr *> &ImmDefMIs); - bool foldImmediate(MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs, - DenseMap<Register, MachineInstr *> &ImmDefMIs, - bool &Deleted); - - /// Finds recurrence cycles, but only ones that formulated around - /// a def operand and a use operand that are tied. If there is a use - /// operand commutable with the tied use operand, find recurrence cycle - /// along that operand as well. - bool findTargetRecurrence(Register Reg, - const SmallSet<Register, 2> &TargetReg, - RecurrenceCycle &RC); - - /// If copy instruction \p MI is a virtual register copy or a copy of a - /// constant physical register to a virtual register, track it in the - /// set CopySrcMIs. If this virtual register was previously seen as a - /// copy, replace the uses of this copy with the previously seen copy's - /// destination register. - bool foldRedundantCopy(MachineInstr &MI); - - /// Is the register \p Reg a non-allocatable physical register? - bool isNAPhysCopy(Register Reg); - - /// If copy instruction \p MI is a non-allocatable virtual<->physical - /// register copy, track it in the \p NAPhysToVirtMIs map. If this - /// non-allocatable physical register was previously copied to a virtual - /// registered and hasn't been clobbered, the virt->phys copy can be - /// deleted. - bool foldRedundantNAPhysCopy( - MachineInstr &MI, DenseMap<Register, MachineInstr *> &NAPhysToVirtMIs); - - bool isLoadFoldable(MachineInstr &MI, - SmallSet<Register, 16> &FoldAsLoadDefCandidates); - - /// Check whether \p MI is understood by the register coalescer - /// but may require some rewriting. - bool isCoalescableCopy(const MachineInstr &MI) { - // SubregToRegs are not interesting, because they are already register - // coalescer friendly. - return MI.isCopy() || (!DisableAdvCopyOpt && - (MI.isRegSequence() || MI.isInsertSubreg() || - MI.isExtractSubreg())); - } + bool optimizeSelect(MachineInstr &MI, + SmallPtrSetImpl<MachineInstr *> &LocalMIs); + bool optimizeCondBranch(MachineInstr &MI); + bool optimizeCoalescableCopy(MachineInstr &MI); + bool optimizeUncoalescableCopy(MachineInstr &MI, + SmallPtrSetImpl<MachineInstr *> &LocalMIs); + bool optimizeRecurrence(MachineInstr &PHI); + bool findNextSource(RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap); + bool isMoveImmediate(MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs, + DenseMap<Register, MachineInstr *> &ImmDefMIs); + bool foldImmediate(MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs, + DenseMap<Register, MachineInstr *> &ImmDefMIs, + bool &Deleted); + + /// Finds recurrence cycles, but only ones that formulated around + /// a def operand and a use operand that are tied. If there is a use + /// operand commutable with the tied use operand, find recurrence cycle + /// along that operand as well. + bool findTargetRecurrence(Register Reg, + const SmallSet<Register, 2> &TargetReg, + RecurrenceCycle &RC); + + /// If copy instruction \p MI is a virtual register copy or a copy of a + /// constant physical register to a virtual register, track it in the + /// set CopySrcMIs. If this virtual register was previously seen as a + /// copy, replace the uses of this copy with the previously seen copy's + /// destination register. + bool foldRedundantCopy(MachineInstr &MI); + + /// Is the register \p Reg a non-allocatable physical register? + bool isNAPhysCopy(Register Reg); + + /// If copy instruction \p MI is a non-allocatable virtual<->physical + /// register copy, track it in the \p NAPhysToVirtMIs map. If this + /// non-allocatable physical register was previously copied to a virtual + /// registered and hasn't been clobbered, the virt->phys copy can be + /// deleted. + bool + foldRedundantNAPhysCopy(MachineInstr &MI, + DenseMap<Register, MachineInstr *> &NAPhysToVirtMIs); + + bool isLoadFoldable(MachineInstr &MI, + SmallSet<Register, 16> &FoldAsLoadDefCandidates); + + /// Check whether \p MI is understood by the register coalescer + /// but may require some rewriting. + bool isCoalescableCopy(const MachineInstr &MI) { + // SubregToRegs are not interesting, because they are already register + // coalescer friendly. + return MI.isCopy() || + (!DisableAdvCopyOpt && (MI.isRegSequence() || MI.isInsertSubreg() || + MI.isExtractSubreg())); + } - /// Check whether \p MI is a copy like instruction that is - /// not recognized by the register coalescer. - bool isUncoalescableCopy(const MachineInstr &MI) { - return MI.isBitcast() || - (!DisableAdvCopyOpt && - (MI.isRegSequenceLike() || MI.isInsertSubregLike() || - MI.isExtractSubregLike())); - } + /// Check whether \p MI is a copy like instruction that is + /// not recognized by the register coalescer. + bool isUncoalescableCopy(const MachineInstr &MI) { + return MI.isBitcast() || (!DisableAdvCopyOpt && (MI.isRegSequenceLike() || + MI.isInsertSubregLike() || + MI.isExtractSubregLike())); + } - MachineInstr &rewriteSource(MachineInstr &CopyLike, - RegSubRegPair Def, RewriteMapTy &RewriteMap); + MachineInstr &rewriteSource(MachineInstr &CopyLike, RegSubRegPair Def, + RewriteMapTy &RewriteMap); - // Set of copies to virtual registers keyed by source register. Never - // holds any physreg which requires def tracking. - DenseMap<RegSubRegPair, MachineInstr *> CopySrcMIs; + // Set of copies to virtual registers keyed by source register. Never + // holds any physreg which requires def tracking. + DenseMap<RegSubRegPair, MachineInstr *> CopySrcMIs; - // MachineFunction::Delegate implementation. Used to maintain CopySrcMIs. - void MF_HandleInsertion(MachineInstr &MI) override { - return; - } + // MachineFunction::Delegate implementation. Used to maintain CopySrcMIs. + void MF_HandleInsertion(MachineInstr &MI) override { return; } - bool getCopySrc(MachineInstr &MI, RegSubRegPair &SrcPair) { - if (!MI.isCopy()) - return false; + bool getCopySrc(MachineInstr &MI, RegSubRegPair &SrcPair) { + if (!MI.isCopy()) + return false; - Register SrcReg = MI.getOperand(1).getReg(); - unsigned SrcSubReg = MI.getOperand(1).getSubReg(); - if (!SrcReg.isVirtual() && !MRI->isConstantPhysReg(SrcReg)) - return false; + Register SrcReg = MI.getOperand(1).getReg(); + unsigned SrcSubReg = MI.getOperand(1).getSubReg(); + if (!SrcReg.isVirtual() && !MRI->isConstantPhysReg(SrcReg)) + return false; - SrcPair = RegSubRegPair(SrcReg, SrcSubReg); - return true; - } + SrcPair = RegSubRegPair(SrcReg, SrcSubReg); + return true; + } - // If a COPY instruction is to be deleted or changed, we should also remove - // it from CopySrcMIs. - void deleteChangedCopy(MachineInstr &MI) { - RegSubRegPair SrcPair; - if (!getCopySrc(MI, SrcPair)) - return; + // If a COPY instruction is to be deleted or changed, we should also remove + // it from CopySrcMIs. + void deleteChangedCopy(MachineInstr &MI) { + RegSubRegPair SrcPair; + if (!getCopySrc(MI, SrcPair)) + return; - auto It = CopySrcMIs.find(SrcPair); - if (It != CopySrcMIs.end() && It->second == &MI) - CopySrcMIs.erase(It); - } + auto It = CopySrcMIs.find(SrcPair); + if (It != CopySrcMIs.end() && It->second == &MI) + CopySrcMIs.erase(It); + } - void MF_HandleRemoval(MachineInstr &MI) override { - deleteChangedCopy(MI); - } + void MF_HandleRemoval(MachineInstr &MI) override { deleteChangedCopy(MI); } - void MF_HandleChangeDesc(MachineInstr &MI, const MCInstrDesc &TID) override - { - deleteChangedCopy(MI); - } - }; - - /// Helper class to hold instructions that are inside recurrence cycles. - /// The recurrence cycle is formulated around 1) a def operand and its - /// tied use operand, or 2) a def operand and a use operand that is commutable - /// with another use operand which is tied to the def operand. In the latter - /// case, index of the tied use operand and the commutable use operand are - /// maintained with CommutePair. - class RecurrenceInstr { - public: - using IndexPair = std::pair<unsigned, unsigned>; - - RecurrenceInstr(MachineInstr *MI) : MI(MI) {} - RecurrenceInstr(MachineInstr *MI, unsigned Idx1, unsigned Idx2) + void MF_HandleChangeDesc(MachineInstr &MI, const MCInstrDesc &TID) override { + deleteChangedCopy(MI); + } +}; + +/// Helper class to hold instructions that are inside recurrence cycles. +/// The recurrence cycle is formulated around 1) a def operand and its +/// tied use operand, or 2) a def operand and a use operand that is commutable +/// with another use operand which is tied to the def operand. In the latter +/// case, index of the tied use operand and the commutable use operand are +/// maintained with CommutePair. +class RecurrenceInstr { +public: + using IndexPair = std::pair<unsigned, unsigned>; + + RecurrenceInstr(MachineInstr *MI) : MI(MI) {} + RecurrenceInstr(MachineInstr *MI, unsigned Idx1, unsigned Idx2) : MI(MI), CommutePair(std::make_pair(Idx1, Idx2)) {} - MachineInstr *getMI() const { return MI; } - std::optional<IndexPair> getCommutePair() const { return CommutePair; } + MachineInstr *getMI() const { return MI; } + std::optional<IndexPair> getCommutePair() const { return CommutePair; } - private: - MachineInstr *MI; - std::optional<IndexPair> CommutePair; - }; +private: + MachineInstr *MI; + std::optional<IndexPair> CommutePair; +}; - /// Helper class to hold a reply for ValueTracker queries. - /// Contains the returned sources for a given search and the instructions - /// where the sources were tracked from. - class ValueTrackerResult { - private: - /// Track all sources found by one ValueTracker query. - SmallVector<RegSubRegPair, 2> RegSrcs; +/// Helper class to hold a reply for ValueTracker queries. +/// Contains the returned sources for a given search and the instructions +/// where the sources were tracked from. +class ValueTrackerResult { +private: + /// Track all sources found by one ValueTracker query. + SmallVector<RegSubRegPair, 2> RegSrcs; - /// Instruction using the sources in 'RegSrcs'. - const MachineInstr *Inst = nullptr; + /// Instruction using the sources in 'RegSrcs'. + const MachineInstr *Inst = nullptr; - public: - ValueTrackerResult() = default; +public: + ValueTrackerResult() = default; - ValueTrackerResult(Register Reg, unsigned SubReg) { - addSource(Reg, SubReg); - } + ValueTrackerResult(Register Reg, unsigned SubReg) { addSource(Reg, SubReg); } - bool isValid() const { return getNumSources() > 0; } + bool isValid() const { return getNumSources() > 0; } - void setInst(const MachineInstr *I) { Inst = I; } - const MachineInstr *getInst() const { return Inst; } + void setInst(const MachineInstr *I) { Inst = I; } + const MachineInstr *getInst() const { return Inst; } - void clear() { - RegSrcs.clear(); - Inst = nullptr; - } + void clear() { + RegSrcs.clear(); + Inst = nullptr; + } - void addSource(Register SrcReg, unsigned SrcSubReg) { - RegSrcs.push_back(RegSubRegPair(SrcReg, SrcSubReg)); - } + void addSource(Register SrcReg, unsigned SrcSubReg) { + RegSrcs.push_back(RegSubRegPair(SrcReg, SrcSubReg)); + } - void setSource(int Idx, Register SrcReg, unsigned SrcSubReg) { - assert(Idx < getNumSources() && "Reg pair source out of index"); - RegSrcs[Idx] = RegSubRegPair(SrcReg, SrcSubReg); - } + void setSource(int Idx, Register SrcReg, unsigned SrcSubReg) { + assert(Idx < getNumSources() && "Reg pair source out of index"); + RegSrcs[Idx] = RegSubRegPair(SrcReg, SrcSubReg); + } - int getNumSources() const { return RegSrcs.size(); } + int getNumSources() const { return RegSrcs.size(); } - RegSubRegPair getSrc(int Idx) const { - return RegSrcs[Idx]; - } + RegSubRegPair getSrc(int Idx) const { return RegSrcs[Idx]; } - Register getSrcReg(int Idx) const { - assert(Idx < getNumSources() && "Reg source out of index"); - return RegSrcs[Idx].Reg; - } + Register getSrcReg(int Idx) const { + assert(Idx < getNumSources() && "Reg source out of index"); + return RegSrcs[Idx].Reg; + } - unsigned getSrcSubReg(int Idx) const { - assert(Idx < getNumSources() && "SubReg source out of index"); - return RegSrcs[Idx].SubReg; - } + unsigned getSrcSubReg(int Idx) const { + assert(Idx < getNumSources() && "SubReg source out of index"); + return RegSrcs[Idx].SubReg; + } - bool operator==(const ValueTrackerResult &Other) const { - if (Other.getInst() != getInst()) - return false; + bool operator==(const ValueTrackerResult &Other) const { + if (Other.getInst() != getInst()) + return false; + + if (Other.getNumSources() != getNumSources()) + return false; - if (Other.getNumSources() != getNumSources()) + for (int i = 0, e = Other.getNumSources(); i != e; ++i) + if (Other.getSrcReg(i) != getSrcReg(i) || + Other.getSrcSubReg(i) != getSrcSubReg(i)) return false; + return true; + } +}; - for (int i = 0, e = Other.getNumSources(); i != e; ++i) - if (Other.getSrcReg(i) != getSrcReg(i) || - Other.getSrcSubReg(i) != getSrcSubReg(i)) - return false; - return true; - } - }; - - /// Helper class to track the possible sources of a value defined by - /// a (chain of) copy related instructions. - /// Given a definition (instruction and definition index), this class - /// follows the use-def chain to find successive suitable sources. - /// The given source can be used to rewrite the definition into - /// def = COPY src. - /// - /// For instance, let us consider the following snippet: - /// v0 = - /// v2 = INSERT_SUBREG v1, v0, sub0 - /// def = COPY v2.sub0 - /// - /// Using a ValueTracker for def = COPY v2.sub0 will give the following - /// suitable sources: - /// v2.sub0 and v0. - /// Then, def can be rewritten into def = COPY v0. - class ValueTracker { - private: - /// The current point into the use-def chain. - const MachineInstr *Def = nullptr; - - /// The index of the definition in Def. - unsigned DefIdx = 0; - - /// The sub register index of the definition. - unsigned DefSubReg; - - /// The register where the value can be found. - Register Reg; - - /// MachineRegisterInfo used to perform tracking. - const MachineRegisterInfo &MRI; - - /// Optional TargetInstrInfo used to perform some complex tracking. - const TargetInstrInfo *TII; - - /// Dispatcher to the right underlying implementation of getNextSource. - ValueTrackerResult getNextSourceImpl(); - - /// Specialized version of getNextSource for Copy instructions. - ValueTrackerResult getNextSourceFromCopy(); - - /// Specialized version of getNextSource for Bitcast instructions. - ValueTrackerResult getNextSourceFromBitcast(); - - /// Specialized version of getNextSource for RegSequence instructions. - ValueTrackerResult getNextSourceFromRegSequence(); - - /// Specialized version of getNextSource for InsertSubreg instructions. - ValueTrackerResult getNextSourceFromInsertSubreg(); - - /// Specialized version of getNextSource for ExtractSubreg instructions. - ValueTrackerResult getNextSourceFromExtractSubreg(); - - /// Specialized version of getNextSource for SubregToReg instructions. - ValueTrackerResult getNextSourceFromSubregToReg(); - - /// Specialized version of getNextSource for PHI instructions. - ValueTrackerResult getNextSourceFromPHI(); - - public: - /// Create a ValueTracker instance for the value defined by \p Reg. - /// \p DefSubReg represents the sub register index the value tracker will - /// track. It does not need to match the sub register index used in the - /// definition of \p Reg. - /// If \p Reg is a physical register, a value tracker constructed with - /// this constructor will not find any alternative source. - /// Indeed, when \p Reg is a physical register that constructor does not - /// know which definition of \p Reg it should track. - /// Use the next constructor to track a physical register. - ValueTracker(Register Reg, unsigned DefSubReg, - const MachineRegisterInfo &MRI, - const TargetInstrInfo *TII = nullptr) - : DefSubReg(DefSubReg), Reg(Reg), MRI(MRI), TII(TII) { - if (!Reg.isPhysical()) { - Def = MRI.getVRegDef(Reg); - DefIdx = MRI.def_begin(Reg).getOperandNo(); - } +/// Helper class to track the possible sources of a value defined by +/// a (chain of) copy related instructions. +/// Given a definition (instruction and definition index), this class +/// follows the use-def chain to find successive suitable sources. +/// The given source can be used to rewrite the definition into +/// def = COPY src. +/// +/// For instance, let us consider the following snippet: +/// v0 = +/// v2 = INSERT_SUBREG v1, v0, sub0 +/// def = COPY v2.sub0 +/// +/// Using a ValueTracker for def = COPY v2.sub0 will give the following +/// suitable sources: +/// v2.sub0 and v0. +/// Then, def can be rewritten into def = COPY v0. +class ValueTracker { +private: + /// The current point into the use-def chain. + const MachineInstr *Def = nullptr; + + /// The index of the definition in Def. + unsigned DefIdx = 0; + + /// The sub register index of the definition. + unsigned DefSubReg; + + /// The register where the value can be found. + Register Reg; + + /// MachineRegisterInfo used to perform tracking. + const MachineRegisterInfo &MRI; + + /// Optional TargetInstrInfo used to perform some complex tracking. + const TargetInstrInfo *TII; + + /// Dispatcher to the right underlying implementation of getNextSource. + ValueTrackerResult getNextSourceImpl(); + + /// Specialized version of getNextSource for Copy instructions. + ValueTrackerResult getNextSourceFromCopy(); + + /// Specialized version of getNextSource for Bitcast instructions. + ValueTrackerResult getNextSourceFromBitcast(); + + /// Specialized version of getNextSource for RegSequence instructions. + ValueTrackerResult getNextSourceFromRegSequence(); + + /// Specialized version of getNextSource for InsertSubreg instructions. + ValueTrackerResult getNextSourceFromInsertSubreg(); + + /// Specialized version of getNextSource for ExtractSubreg instructions. + ValueTrackerResult getNextSourceFromExtractSubreg(); + + /// Specialized version of getNextSource for SubregToReg instructions. + ValueTrackerResult getNextSourceFromSubregToReg(); + + /// Specialized version of getNextSource for PHI instructions. + ValueTrackerResult getNextSourceFromPHI(); + +public: + /// Create a ValueTracker instance for the value defined by \p Reg. + /// \p DefSubReg represents the sub register index the value tracker will + /// track. It does not need to match the sub register index used in the + /// definition of \p Reg. + /// If \p Reg is a physical register, a value tracker constructed with + /// this constructor will not find any alternative source. + /// Indeed, when \p Reg is a physical register that constructor does not + /// know which definition of \p Reg it should track. + /// Use the next constructor to track a physical register. + ValueTracker(Register Reg, unsigned DefSubReg, const MachineRegisterInfo &MRI, + const TargetInstrInfo *TII = nullptr) + : DefSubReg(DefSubReg), Reg(Reg), MRI(MRI), TII(TII) { + if (!Reg.isPhysical()) { + Def = MRI.getVRegDef(Reg); + DefIdx = MRI.def_begin(Reg).getOperandNo(); } + } - /// Following the use-def chain, get the next available source - /// for the tracked value. - /// \return A ValueTrackerResult containing a set of registers - /// and sub registers with tracked values. A ValueTrackerResult with - /// an empty set of registers means no source was found. - ValueTrackerResult getNextSource(); - }; + /// Following the use-def chain, get the next available source + /// for the tracked value. + /// \return A ValueTrackerResult containing a set of registers + /// and sub registers with tracked values. A ValueTrackerResult with + /// an empty set of registers means no source was found. + ValueTrackerResult getNextSource(); +}; } // end anonymous namespace @@ -485,12 +473,12 @@ char PeepholeOptimizer::ID = 0; char &llvm::PeepholeOptimizerID = PeepholeOptimizer::ID; -INITIALIZE_PASS_BEGIN(PeepholeOptimizer, DEBUG_TYPE, - "Peephole Optimizations", false, false) +INITIALIZE_PASS_BEGIN(PeepholeOptimizer, DEBUG_TYPE, "Peephole Optimizations", + false, false) INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass) -INITIALIZE_PASS_END(PeepholeOptimizer, DEBUG_TYPE, - "Peephole Optimizations", false, false) +INITIALIZE_PASS_END(PeepholeOptimizer, DEBUG_TYPE, "Peephole Optimizations", + false, false) /// If instruction is a copy-like instruction, i.e. it reads a single register /// and writes a single register and it does not modify the source, and if the @@ -500,9 +488,9 @@ INITIALIZE_PASS_END(PeepholeOptimizer, DEBUG_TYPE, /// Do not generate an EXTRACT that is used only in a debug use, as this changes /// the code. Since this code does not currently share EXTRACTs, just ignore all /// debug uses. -bool PeepholeOptimizer:: -optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, - SmallPtrSetImpl<MachineInstr*> &LocalMIs) { +bool PeepholeOptimizer::optimizeExtInstr( + MachineInstr &MI, MachineBasicBlock &MBB, + SmallPtrSetImpl<MachineInstr *> &LocalMIs) { Register SrcReg, DstReg; unsigned SubIdx; if (!TII->isCoalescableExtInstr(MI, SrcReg, DstReg, SubIdx)) @@ -532,15 +520,15 @@ optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, // The source has other uses. See if we can replace the other uses with use of // the result of the extension. - SmallPtrSet<MachineBasicBlock*, 4> ReachedBBs; + SmallPtrSet<MachineBasicBlock *, 4> ReachedBBs; for (MachineInstr &UI : MRI->use_nodbg_instructions(DstReg)) ReachedBBs.insert(UI.getParent()); // Uses that are in the same BB of uses of the result of the instruction. - SmallVector<MachineOperand*, 8> Uses; + SmallVector<MachineOperand *, 8> Uses; // Uses that the result of the instruction can reach. - SmallVector<MachineOperand*, 8> ExtendedUses; + SmallVector<MachineOperand *, 8> ExtendedUses; bool ExtendLife = true; for (MachineOperand &UseMO : MRI->use_nodbg_operands(SrcReg)) { @@ -605,7 +593,7 @@ optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, // Now replace all uses. bool Changed = false; if (!Uses.empty()) { - SmallPtrSet<MachineBasicBlock*, 4> PHIBBs; + SmallPtrSet<MachineBasicBlock *, 4> PHIBBs; // Look for PHI uses of the extended result, we don't want to extend the // liveness of a PHI input. It breaks all kinds of assumptions down @@ -647,7 +635,7 @@ optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, Register NewVR = MRI->createVirtualRegister(RC); BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(), TII->get(TargetOpcode::COPY), NewVR) - .addReg(DstReg, 0, SubIdx); + .addReg(DstReg, 0, SubIdx); if (UseSrcSubIdx) UseMO->setSubReg(0); @@ -685,8 +673,8 @@ bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr &MI) { } /// Optimize a select instruction. -bool PeepholeOptimizer::optimizeSelect(MachineInstr &MI, - SmallPtrSetImpl<MachineInstr *> &LocalMIs) { +bool PeepholeOptimizer::optimizeSelect( + MachineInstr &MI, SmallPtrSetImpl<MachineInstr *> &LocalMIs) { unsigned TrueOp = 0; unsigned FalseOp = 0; bool Optimizable = false; @@ -814,10 +802,10 @@ bool PeepholeOptimizer::findNextSource(RegSubRegPair RegSubReg, /// successfully traverse a PHI instruction and find suitable sources coming /// from its edges. By inserting a new PHI, we provide a rewritten PHI def /// suitable to be used in a new COPY instruction. -static MachineInstr & -insertPHI(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, - const SmallVectorImpl<RegSubRegPair> &SrcRegs, - MachineInstr &OrigPHI) { +static MachineInstr &insertPHI(MachineRegisterInfo &MRI, + const TargetInstrInfo &TII, + const SmallVectorImpl<RegSubRegPair> &SrcRegs, + MachineInstr &OrigPHI) { assert(!SrcRegs.empty() && "No sources to create a PHI instruction?"); const TargetRegisterClass *NewRC = MRI.getRegClass(SrcRegs[0].Reg); @@ -849,7 +837,7 @@ namespace { class Rewriter { protected: MachineInstr &CopyLike; - unsigned CurrentSrcIdx = 0; ///< The index of the source being rewritten. + unsigned CurrentSrcIdx = 0; ///< The index of the source being rewritten. public: Rewriter(MachineInstr &CopyLike) : CopyLike(CopyLike) {} virtual ~Rewriter() = default; @@ -925,7 +913,7 @@ public: /// Helper class to rewrite uncoalescable copy like instructions /// into new COPY (coalescable friendly) instructions. class UncoalescableRewriter : public Rewriter { - unsigned NumDefs; ///< Number of defs in the bitcast. + unsigned NumDefs; ///< Number of defs in the bitcast. public: UncoalescableRewriter(MachineInstr &MI) : Rewriter(MI) { @@ -1039,8 +1027,8 @@ public: if (MOExtractedReg.getSubReg()) return false; - Src = RegSubRegPair(MOExtractedReg.getReg(), - CopyLike.getOperand(2).getImm()); + Src = + RegSubRegPair(MOExtractedReg.getReg(), CopyLike.getOperand(2).getImm()); // We want to track something that is compatible with the definition. const MachineOperand &MODef = CopyLike.getOperand(0); @@ -1281,9 +1269,9 @@ bool PeepholeOptimizer::optimizeCoalescableCopy(MachineInstr &MI) { /// PeepholeOptimizer::findNextSource. Right now this is only used to handle /// Uncoalescable copies, since they are copy like instructions that aren't /// recognized by the register allocator. -MachineInstr & -PeepholeOptimizer::rewriteSource(MachineInstr &CopyLike, - RegSubRegPair Def, RewriteMapTy &RewriteMap) { +MachineInstr &PeepholeOptimizer::rewriteSource(MachineInstr &CopyLike, + RegSubRegPair Def, + RewriteMapTy &RewriteMap) { assert(!Def.Reg.isPhysical() && "We do not rewrite physical registers"); // Find the new source to use in the COPY rewrite. @@ -1685,7 +1673,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { // To perform this, the following set keeps track of the MIs already seen // during the scan, if a MI is not in the set, it is assumed to be located // after. Newly created MIs have to be inserted in the set as well. - SmallPtrSet<MachineInstr*, 16> LocalMIs; + SmallPtrSet<MachineInstr *, 16> LocalMIs; SmallSet<Register, 4> ImmDefRegs; DenseMap<Register, MachineInstr *> ImmDefMIs; SmallSet<Register, 16> FoldAsLoadDefCandidates; @@ -1702,7 +1690,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { bool IsLoopHeader = MLI->isLoopHeader(&MBB); for (MachineBasicBlock::iterator MII = MBB.begin(), MIE = MBB.end(); - MII != MIE; ) { + MII != MIE;) { MachineInstr *MI = &*MII; // We may be erasing MI below, increment MII now. ++MII; @@ -1826,8 +1814,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { // foldable uses earlier in the argument list. Since we don't restart // iteration, we'd miss such cases. const MCInstrDesc &MIDesc = MI->getDesc(); - for (unsigned i = MIDesc.getNumDefs(); i != MI->getNumOperands(); - ++i) { + for (unsigned i = MIDesc.getNumDefs(); i != MI->getNumOperands(); ++i) { const MachineOperand &MOp = MI->getOperand(i); if (!MOp.isReg()) continue; @@ -2038,9 +2025,9 @@ ValueTrackerResult ValueTracker::getNextSourceFromInsertSubreg() { // Get the TRI and check if the inserted sub-register overlaps with the // sub-register we are tracking. const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); - if (!TRI || - !(TRI->getSubRegIndexLaneMask(DefSubReg) & - TRI->getSubRegIndexLaneMask(InsertedReg.SubIdx)).none()) + if (!TRI || !(TRI->getSubRegIndexLaneMask(DefSubReg) & + TRI->getSubRegIndexLaneMask(InsertedReg.SubIdx)) + .none()) return ValueTrackerResult(); // At this point, the value is available in v0 via the same subreg // we used for Def. @@ -2048,8 +2035,8 @@ ValueTrackerResult ValueTracker::getNextSourceFromInsertSubreg() { } ValueTrackerResult ValueTracker::getNextSourceFromExtractSubreg() { - assert((Def->isExtractSubreg() || - Def->isExtractSubregLike()) && "Invalid definition"); + assert((Def->isExtractSubreg() || Def->isExtractSubregLike()) && + "Invalid definition"); // We are looking at: // Def = EXTRACT_SUBREG v0, sub0 |