Date: Tue, 15 May 2018 17:50:19 +0000 (UTC) From: Brooks Davis <brooks@FreeBSD.org> To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r470040 - in head/devel/llvm60: . files Message-ID: <201805151750.w4FHoJI1094520@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: brooks Date: Tue May 15 17:50:19 2018 New Revision: 470040 URL: https://svnweb.freebsd.org/changeset/ports/470040 Log: Merge r322325 from upstream. This allows devel/godot to build in a reasionable abount of time: PeepholeOpt cleanup/refactor; NFC - Less unnecessary use of `auto` - Add early `using RegSubRegPair(AndIdx) =` to avoid countless `TargetInstrInfo::` qualifications. - Use references instead of pointers where possible. - Remove unused parameters. - Rewrite the CopyRewriter class hierarchy: - Pull out uncoalescable copy rewriting functionality into PeepholeOptimizer class. - Use an abstract base class to make it clear that rewriters are independent. - Remove unnecessary \brief in doxygen comments. - Remove unused constructor and method from ValueTracker. - Replace UseAdvancedTracking of ValueTracker with DisableAdvCopyOpt use. PR: 228261 Reported by: FreeBSD@ShaneWare.Biz Added: head/devel/llvm60/files/patch-svn-r322325 (contents, props changed) Modified: head/devel/llvm60/Makefile Modified: head/devel/llvm60/Makefile ============================================================================== --- head/devel/llvm60/Makefile Tue May 15 17:39:15 2018 (r470039) +++ head/devel/llvm60/Makefile Tue May 15 17:50:19 2018 (r470040) @@ -2,7 +2,7 @@ PORTNAME= llvm DISTVERSION= 6.0.0 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= devel lang MASTER_SITES= http://${PRE_}releases.llvm.org/${LLVM_RELEASE}/${RCDIR} PKGNAMESUFFIX= ${LLVM_SUFFIX} Added: head/devel/llvm60/files/patch-svn-r322325 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/devel/llvm60/files/patch-svn-r322325 Tue May 15 17:50:19 2018 (r470040) @@ -0,0 +1,1589 @@ +r322325: + +PeepholeOpt cleanup/refactor; NFC + +- Less unnecessary use of `auto` +- Add early `using RegSubRegPair(AndIdx) =` to avoid countless + `TargetInstrInfo::` qualifications. +- Use references instead of pointers where possible. +- Remove unused parameters. +- Rewrite the CopyRewriter class hierarchy: + - Pull out uncoalescable copy rewriting functionality into + PeepholeOptimizer class. + - Use an abstract base class to make it clear that rewriters are + independent. +- Remove unnecessary \brief in doxygen comments. +- Remove unused constructor and method from ValueTracker. +- Replace UseAdvancedTracking of ValueTracker with DisableAdvCopyOpt use. + +--- lib/CodeGen/PeepholeOptimizer.cpp.orig ++++ lib/CodeGen/PeepholeOptimizer.cpp +@@ -98,6 +98,8 @@ + #include <utility> + + using namespace llvm; ++using RegSubRegPair = TargetInstrInfo::RegSubRegPair; ++using RegSubRegPairAndIdx = TargetInstrInfo::RegSubRegPairAndIdx; + + #define DEBUG_TYPE "peephole-opt" + +@@ -110,6 +112,9 @@ + 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")); +@@ -132,11 +137,11 @@ + "of commuting operands")); + + +-STATISTIC(NumReuse, "Number of extension results reused"); +-STATISTIC(NumCmps, "Number of compares eliminated"); +-STATISTIC(NumImmFold, "Number of move immediate folded"); +-STATISTIC(NumLoadFold, "Number of loads folded"); +-STATISTIC(NumSelects, "Number of selects optimized"); ++STATISTIC(NumReuse, "Number of extension results reused"); ++STATISTIC(NumCmps, "Number of compares eliminated"); ++STATISTIC(NumImmFold, "Number of move immediate folded"); ++STATISTIC(NumLoadFold, "Number of loads folded"); ++STATISTIC(NumSelects, "Number of selects optimized"); + STATISTIC(NumUncoalescableCopies, "Number of uncoalescable copies optimized"); + STATISTIC(NumRewrittenCopies, "Number of copies rewritten"); + STATISTIC(NumNAPhysCopies, "Number of non-allocatable physical copies removed"); +@@ -149,9 +154,9 @@ + class PeepholeOptimizer : public MachineFunctionPass { + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; +- MachineRegisterInfo *MRI; +- MachineDominatorTree *DT; // Machine dominator tree +- MachineLoopInfo *MLI; ++ MachineRegisterInfo *MRI; ++ MachineDominatorTree *DT; // Machine dominator tree ++ MachineLoopInfo *MLI; + + public: + static char ID; // Pass identification +@@ -173,31 +178,28 @@ + } + } + +- /// \brief Track Def -> Use info used for rewriting copies. +- using RewriteMapTy = +- SmallDenseMap<TargetInstrInfo::RegSubRegPair, ValueTrackerResult>; ++ /// Track Def -> Use info used for rewriting copies. ++ using RewriteMapTy = SmallDenseMap<RegSubRegPair, ValueTrackerResult>; + +- /// \brief Sequence of instructions that formulate recurrence cycle. ++ /// Sequence of instructions that formulate recurrence cycle. + using RecurrenceCycle = SmallVector<RecurrenceInstr, 4>; + + private: +- bool optimizeCmpInstr(MachineInstr *MI, MachineBasicBlock *MBB); +- bool optimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, ++ bool optimizeCmpInstr(MachineInstr &MI); ++ bool optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, + SmallPtrSetImpl<MachineInstr*> &LocalMIs); +- bool optimizeSelect(MachineInstr *MI, ++ bool optimizeSelect(MachineInstr &MI, + SmallPtrSetImpl<MachineInstr *> &LocalMIs); +- bool optimizeCondBranch(MachineInstr *MI); +- bool optimizeCoalescableCopy(MachineInstr *MI); +- bool optimizeUncoalescableCopy(MachineInstr *MI, ++ bool optimizeCondBranch(MachineInstr &MI); ++ bool optimizeCoalescableCopy(MachineInstr &MI); ++ bool optimizeUncoalescableCopy(MachineInstr &MI, + SmallPtrSetImpl<MachineInstr *> &LocalMIs); + bool optimizeRecurrence(MachineInstr &PHI); +- bool findNextSource(unsigned Reg, unsigned SubReg, +- RewriteMapTy &RewriteMap); +- bool isMoveImmediate(MachineInstr *MI, ++ bool findNextSource(RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap); ++ bool isMoveImmediate(MachineInstr &MI, + SmallSet<unsigned, 4> &ImmDefRegs, + DenseMap<unsigned, MachineInstr*> &ImmDefMIs); +- bool foldImmediate(MachineInstr *MI, MachineBasicBlock *MBB, +- SmallSet<unsigned, 4> &ImmDefRegs, ++ bool foldImmediate(MachineInstr &MI, SmallSet<unsigned, 4> &ImmDefRegs, + DenseMap<unsigned, MachineInstr*> &ImmDefMIs); + + /// \brief Finds recurrence cycles, but only ones that formulated around +@@ -212,11 +214,11 @@ + /// the set \p CopySrcRegs and \p CopyMIs. 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, ++ bool foldRedundantCopy(MachineInstr &MI, + SmallSet<unsigned, 4> &CopySrcRegs, + DenseMap<unsigned, MachineInstr *> &CopyMIs); + +- /// \brief Is the register \p Reg a non-allocatable physical register? ++ /// Is the register \p Reg a non-allocatable physical register? + bool isNAPhysCopy(unsigned Reg); + + /// \brief If copy instruction \p MI is a non-allocatable virtual<->physical +@@ -224,11 +226,10 @@ + /// 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, ++ bool foldRedundantNAPhysCopy(MachineInstr &MI, + DenseMap<unsigned, MachineInstr *> &NAPhysToVirtMIs); + +- bool isLoadFoldable(MachineInstr *MI, ++ bool isLoadFoldable(MachineInstr &MI, + SmallSet<unsigned, 16> &FoldAsLoadDefCandidates); + + /// \brief Check whether \p MI is understood by the register coalescer +@@ -249,10 +250,13 @@ + (MI.isRegSequenceLike() || MI.isInsertSubregLike() || + MI.isExtractSubregLike())); + } ++ ++ MachineInstr &rewriteSource(MachineInstr &CopyLike, ++ RegSubRegPair Def, RewriteMapTy &RewriteMap); + }; + +- /// \brief Helper class to hold instructions that are inside recurrence +- /// cycles. The recurrence cycle is formulated around 1) a def operand and its ++ /// 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 +@@ -273,13 +277,13 @@ + Optional<IndexPair> CommutePair; + }; + +- /// \brief 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. ++ /// 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<TargetInstrInfo::RegSubRegPair, 2> RegSrcs; ++ SmallVector<RegSubRegPair, 2> RegSrcs; + + /// Instruction using the sources in 'RegSrcs'. + const MachineInstr *Inst = nullptr; +@@ -302,16 +306,20 @@ + } + + void addSource(unsigned SrcReg, unsigned SrcSubReg) { +- RegSrcs.push_back(TargetInstrInfo::RegSubRegPair(SrcReg, SrcSubReg)); ++ RegSrcs.push_back(RegSubRegPair(SrcReg, SrcSubReg)); + } + + void setSource(int Idx, unsigned SrcReg, unsigned SrcSubReg) { + assert(Idx < getNumSources() && "Reg pair source out of index"); +- RegSrcs[Idx] = TargetInstrInfo::RegSubRegPair(SrcReg, SrcSubReg); ++ RegSrcs[Idx] = RegSubRegPair(SrcReg, SrcSubReg); + } + + int getNumSources() const { return RegSrcs.size(); } + ++ RegSubRegPair getSrc(int Idx) const { ++ return RegSrcs[Idx]; ++ } ++ + unsigned getSrcReg(int Idx) const { + assert(Idx < getNumSources() && "Reg source out of index"); + return RegSrcs[Idx].Reg; +@@ -367,59 +375,41 @@ + /// The register where the value can be found. + unsigned Reg; + +- /// Specifiy whether or not the value tracking looks through +- /// complex instructions. When this is false, the value tracker +- /// bails on everything that is not a copy or a bitcast. +- /// +- /// Note: This could have been implemented as a specialized version of +- /// the ValueTracker class but that would have complicated the code of +- /// the users of this class. +- bool UseAdvancedTracking; +- + /// MachineRegisterInfo used to perform tracking. + const MachineRegisterInfo &MRI; + +- /// Optional TargetInstrInfo used to perform some complex +- /// tracking. ++ /// Optional TargetInstrInfo used to perform some complex tracking. + const TargetInstrInfo *TII; + +- /// \brief Dispatcher to the right underlying implementation of +- /// getNextSource. ++ /// Dispatcher to the right underlying implementation of getNextSource. + ValueTrackerResult getNextSourceImpl(); + +- /// \brief Specialized version of getNextSource for Copy instructions. ++ /// Specialized version of getNextSource for Copy instructions. + ValueTrackerResult getNextSourceFromCopy(); + +- /// \brief Specialized version of getNextSource for Bitcast instructions. ++ /// Specialized version of getNextSource for Bitcast instructions. + ValueTrackerResult getNextSourceFromBitcast(); + +- /// \brief Specialized version of getNextSource for RegSequence +- /// instructions. ++ /// Specialized version of getNextSource for RegSequence instructions. + ValueTrackerResult getNextSourceFromRegSequence(); + +- /// \brief Specialized version of getNextSource for InsertSubreg +- /// instructions. ++ /// Specialized version of getNextSource for InsertSubreg instructions. + ValueTrackerResult getNextSourceFromInsertSubreg(); + +- /// \brief Specialized version of getNextSource for ExtractSubreg +- /// instructions. ++ /// Specialized version of getNextSource for ExtractSubreg instructions. + ValueTrackerResult getNextSourceFromExtractSubreg(); + +- /// \brief Specialized version of getNextSource for SubregToReg +- /// instructions. ++ /// Specialized version of getNextSource for SubregToReg instructions. + ValueTrackerResult getNextSourceFromSubregToReg(); + +- /// \brief Specialized version of getNextSource for PHI instructions. ++ /// Specialized version of getNextSource for PHI instructions. + ValueTrackerResult getNextSourceFromPHI(); + + public: +- /// \brief Create a ValueTracker instance for the value defined by \p Reg. ++ /// 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. +- /// \p UseAdvancedTracking specifies whether or not the value tracker looks +- /// through complex instructions. By default (false), it handles only copy +- /// and bitcast instructions. + /// 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 +@@ -427,46 +417,20 @@ + /// Use the next constructor to track a physical register. + ValueTracker(unsigned Reg, unsigned DefSubReg, + const MachineRegisterInfo &MRI, +- bool UseAdvancedTracking = false, + const TargetInstrInfo *TII = nullptr) +- : DefSubReg(DefSubReg), Reg(Reg), +- UseAdvancedTracking(UseAdvancedTracking), MRI(MRI), TII(TII) { ++ : DefSubReg(DefSubReg), Reg(Reg), MRI(MRI), TII(TII) { + if (!TargetRegisterInfo::isPhysicalRegister(Reg)) { + Def = MRI.getVRegDef(Reg); + DefIdx = MRI.def_begin(Reg).getOperandNo(); + } + } + +- /// \brief Create a ValueTracker instance for the value defined by +- /// the pair \p MI, \p DefIdx. +- /// Unlike the other constructor, the value tracker produced by this one +- /// may be able to find a new source when the definition is a physical +- /// register. +- /// This could be useful to rewrite target specific instructions into +- /// generic copy instructions. +- ValueTracker(const MachineInstr &MI, unsigned DefIdx, unsigned DefSubReg, +- const MachineRegisterInfo &MRI, +- bool UseAdvancedTracking = false, +- const TargetInstrInfo *TII = nullptr) +- : Def(&MI), DefIdx(DefIdx), DefSubReg(DefSubReg), +- UseAdvancedTracking(UseAdvancedTracking), MRI(MRI), TII(TII) { +- assert(DefIdx < Def->getDesc().getNumDefs() && +- Def->getOperand(DefIdx).isReg() && "Invalid definition"); +- Reg = Def->getOperand(DefIdx).getReg(); +- } +- + /// \brief 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(); +- +- /// \brief Get the last register where the initial value can be found. +- /// Initially this is the register of the definition. +- /// Then, after each successful call to getNextSource, this is the +- /// register of the last source. +- unsigned getReg() const { return Reg; } + }; + + } // end anonymous namespace +@@ -476,11 +440,11 @@ + char &llvm::PeepholeOptimizerID = PeepholeOptimizer::ID; + + INITIALIZE_PASS_BEGIN(PeepholeOptimizer, DEBUG_TYPE, +- "Peephole Optimizations", false, false) ++ "Peephole Optimizations", false, false) + INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) + INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) + INITIALIZE_PASS_END(PeepholeOptimizer, DEBUG_TYPE, +- "Peephole Optimizations", false, false) ++ "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 +@@ -491,10 +455,10 @@ + /// the code. Since this code does not currently share EXTRACTs, just ignore all + /// debug uses. + bool PeepholeOptimizer:: +-optimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, ++optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, + SmallPtrSetImpl<MachineInstr*> &LocalMIs) { + unsigned SrcReg, DstReg, SubIdx; +- if (!TII->isCoalescableExtInstr(*MI, SrcReg, DstReg, SubIdx)) ++ if (!TII->isCoalescableExtInstr(MI, SrcReg, DstReg, SubIdx)) + return false; + + if (TargetRegisterInfo::isPhysicalRegister(DstReg) || +@@ -535,7 +499,7 @@ + bool ExtendLife = true; + for (MachineOperand &UseMO : MRI->use_nodbg_operands(SrcReg)) { + MachineInstr *UseMI = UseMO.getParent(); +- if (UseMI == MI) ++ if (UseMI == &MI) + continue; + + if (UseMI->isPHI()) { +@@ -568,7 +532,7 @@ + continue; + + MachineBasicBlock *UseMBB = UseMI->getParent(); +- if (UseMBB == MBB) { ++ if (UseMBB == &MBB) { + // Local uses that come after the extension. + if (!LocalMIs.count(UseMI)) + Uses.push_back(&UseMO); +@@ -576,7 +540,7 @@ + // Non-local uses where the result of the extension is used. Always + // replace these unless it's a PHI. + Uses.push_back(&UseMO); +- } else if (Aggressive && DT->dominates(MBB, UseMBB)) { ++ } else if (Aggressive && DT->dominates(&MBB, UseMBB)) { + // We may want to extend the live range of the extension result in order + // to replace these uses. + ExtendedUses.push_back(&UseMO); +@@ -640,19 +604,18 @@ + /// against already sets (or could be modified to set) the same flag as the + /// compare, then we can remove the comparison and use the flag from the + /// previous instruction. +-bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr *MI, +- MachineBasicBlock *MBB) { ++bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr &MI) { + // If this instruction is a comparison against zero and isn't comparing a + // physical register, we can try to optimize it. + unsigned SrcReg, SrcReg2; + int CmpMask, CmpValue; +- if (!TII->analyzeCompare(*MI, SrcReg, SrcReg2, CmpMask, CmpValue) || ++ if (!TII->analyzeCompare(MI, SrcReg, SrcReg2, CmpMask, CmpValue) || + TargetRegisterInfo::isPhysicalRegister(SrcReg) || + (SrcReg2 != 0 && TargetRegisterInfo::isPhysicalRegister(SrcReg2))) + return false; + + // Attempt to optimize the comparison instruction. +- if (TII->optimizeCompareInstr(*MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI)) { ++ if (TII->optimizeCompareInstr(MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI)) { + ++NumCmps; + return true; + } +@@ -661,27 +624,26 @@ + } + + /// Optimize a select instruction. +-bool PeepholeOptimizer::optimizeSelect(MachineInstr *MI, ++bool PeepholeOptimizer::optimizeSelect(MachineInstr &MI, + SmallPtrSetImpl<MachineInstr *> &LocalMIs) { + unsigned TrueOp = 0; + unsigned FalseOp = 0; + bool Optimizable = false; + SmallVector<MachineOperand, 4> Cond; +- if (TII->analyzeSelect(*MI, Cond, TrueOp, FalseOp, Optimizable)) ++ if (TII->analyzeSelect(MI, Cond, TrueOp, FalseOp, Optimizable)) + return false; + if (!Optimizable) + return false; +- if (!TII->optimizeSelect(*MI, LocalMIs)) ++ if (!TII->optimizeSelect(MI, LocalMIs)) + return false; +- MI->eraseFromParent(); ++ MI.eraseFromParent(); + ++NumSelects; + return true; + } + +-/// \brief Check if a simpler conditional branch can be +-/// generated +-bool PeepholeOptimizer::optimizeCondBranch(MachineInstr *MI) { +- return TII->optimizeCondBranch(*MI); ++/// Check if a simpler conditional branch can be generated. ++bool PeepholeOptimizer::optimizeCondBranch(MachineInstr &MI) { ++ return TII->optimizeCondBranch(MI); + } + + /// \brief Try to find the next source that share the same register file +@@ -695,30 +657,29 @@ + /// share the same register file as \p Reg and \p SubReg. The client should + /// then be capable to rewrite all intermediate PHIs to get the next source. + /// \return False if no alternative sources are available. True otherwise. +-bool PeepholeOptimizer::findNextSource(unsigned Reg, unsigned SubReg, ++bool PeepholeOptimizer::findNextSource(RegSubRegPair RegSubReg, + RewriteMapTy &RewriteMap) { + // Do not try to find a new source for a physical register. + // So far we do not have any motivating example for doing that. + // Thus, instead of maintaining untested code, we will revisit that if + // that changes at some point. ++ unsigned Reg = RegSubReg.Reg; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return false; + const TargetRegisterClass *DefRC = MRI->getRegClass(Reg); + +- SmallVector<TargetInstrInfo::RegSubRegPair, 4> SrcToLook; +- TargetInstrInfo::RegSubRegPair CurSrcPair(Reg, SubReg); ++ SmallVector<RegSubRegPair, 4> SrcToLook; ++ RegSubRegPair CurSrcPair = RegSubReg; + SrcToLook.push_back(CurSrcPair); + + unsigned PHICount = 0; +- while (!SrcToLook.empty() && PHICount < RewritePHILimit) { +- TargetInstrInfo::RegSubRegPair Pair = SrcToLook.pop_back_val(); ++ do { ++ CurSrcPair = SrcToLook.pop_back_val(); + // As explained above, do not handle physical registers +- if (TargetRegisterInfo::isPhysicalRegister(Pair.Reg)) ++ if (TargetRegisterInfo::isPhysicalRegister(CurSrcPair.Reg)) + return false; + +- CurSrcPair = Pair; +- ValueTracker ValTracker(CurSrcPair.Reg, CurSrcPair.SubReg, *MRI, +- !DisableAdvCopyOpt, TII); ++ ValueTracker ValTracker(CurSrcPair.Reg, CurSrcPair.SubReg, *MRI, TII); + + // Follow the chain of copies until we find a more suitable source, a phi + // or have to abort. +@@ -747,14 +708,17 @@ + unsigned NumSrcs = Res.getNumSources(); + if (NumSrcs > 1) { + PHICount++; ++ if (PHICount >= RewritePHILimit) { ++ DEBUG(dbgs() << "findNextSource: PHI limit reached\n"); ++ return false; ++ } ++ + for (unsigned i = 0; i < NumSrcs; ++i) +- SrcToLook.push_back(TargetInstrInfo::RegSubRegPair( +- Res.getSrcReg(i), Res.getSrcSubReg(i))); ++ SrcToLook.push_back(Res.getSrc(i)); + break; + } + +- CurSrcPair.Reg = Res.getSrcReg(0); +- CurSrcPair.SubReg = Res.getSrcSubReg(0); ++ CurSrcPair = Res.getSrc(0); + // Do not extend the live-ranges of physical registers as they add + // constraints to the register allocator. Moreover, if we want to extend + // the live-range of a physical register, unlike SSA virtual register, +@@ -764,7 +728,8 @@ + + // Keep following the chain if the value isn't any better yet. + const TargetRegisterClass *SrcRC = MRI->getRegClass(CurSrcPair.Reg); +- if (!TRI->shouldRewriteCopySrc(DefRC, SubReg, SrcRC, CurSrcPair.SubReg)) ++ if (!TRI->shouldRewriteCopySrc(DefRC, RegSubReg.SubReg, SrcRC, ++ CurSrcPair.SubReg)) + continue; + + // We currently cannot deal with subreg operands on PHI instructions +@@ -775,7 +740,7 @@ + // We found a suitable source, and are done with this chain. + break; + } +- } ++ } while (!SrcToLook.empty()); + + // If we did not find a more suitable source, there is nothing to optimize. + return CurSrcPair.Reg != Reg; +@@ -786,54 +751,50 @@ + /// 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<TargetInstrInfo::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); ++ const TargetRegisterClass *NewRC = MRI.getRegClass(SrcRegs[0].Reg); + // NewRC is only correct if no subregisters are involved. findNextSource() + // should have rejected those cases already. + assert(SrcRegs[0].SubReg == 0 && "should not have subreg operand"); +- unsigned NewVR = MRI->createVirtualRegister(NewRC); +- MachineBasicBlock *MBB = OrigPHI->getParent(); +- MachineInstrBuilder MIB = BuildMI(*MBB, OrigPHI, OrigPHI->getDebugLoc(), +- TII->get(TargetOpcode::PHI), NewVR); ++ unsigned NewVR = MRI.createVirtualRegister(NewRC); ++ MachineBasicBlock *MBB = OrigPHI.getParent(); ++ MachineInstrBuilder MIB = BuildMI(*MBB, &OrigPHI, OrigPHI.getDebugLoc(), ++ TII.get(TargetOpcode::PHI), NewVR); + + unsigned MBBOpIdx = 2; +- for (auto RegPair : SrcRegs) { ++ for (const RegSubRegPair &RegPair : SrcRegs) { + MIB.addReg(RegPair.Reg, 0, RegPair.SubReg); +- MIB.addMBB(OrigPHI->getOperand(MBBOpIdx).getMBB()); ++ MIB.addMBB(OrigPHI.getOperand(MBBOpIdx).getMBB()); + // Since we're extended the lifetime of RegPair.Reg, clear the + // kill flags to account for that and make RegPair.Reg reaches + // the new PHI. +- MRI->clearKillFlags(RegPair.Reg); ++ MRI.clearKillFlags(RegPair.Reg); + MBBOpIdx += 2; + } + +- return MIB; ++ return *MIB; + } + + namespace { + +-/// \brief Helper class to rewrite the arguments of a copy-like instruction. +-class CopyRewriter { ++/// Interface to query instructions amenable to copy rewriting. ++class Rewriter { + protected: +- /// The copy-like instruction. + MachineInstr &CopyLike; +- +- /// The index of the source being rewritten. +- unsigned CurrentSrcIdx = 0; +- ++ unsigned CurrentSrcIdx = 0; ///< The index of the source being rewritten. + public: +- CopyRewriter(MachineInstr &MI) : CopyLike(MI) {} +- virtual ~CopyRewriter() = default; ++ Rewriter(MachineInstr &CopyLike) : CopyLike(CopyLike) {} ++ virtual ~Rewriter() {} + + /// \brief Get the next rewritable source (SrcReg, SrcSubReg) and +- /// the related value that it affects (TrackReg, TrackSubReg). ++ /// the related value that it affects (DstReg, DstSubReg). + /// A source is considered rewritable if its register class and the +- /// register class of the related TrackReg may not be register ++ /// register class of the related DstReg may not be register + /// coalescer friendly. In other words, given a copy-like instruction + /// not all the arguments may be returned at rewritable source, since + /// some arguments are none to be register coalescer friendly. +@@ -848,137 +809,72 @@ + /// the only source this instruction has: + /// (SrcReg, SrcSubReg) = (src, srcSubIdx). + /// This source defines the whole definition, i.e., +- /// (TrackReg, TrackSubReg) = (dst, dstSubIdx). ++ /// (DstReg, DstSubReg) = (dst, dstSubIdx). + /// + /// The second and subsequent calls will return false, as there is only one + /// rewritable source. + /// + /// \return True if a rewritable source has been found, false otherwise. + /// The output arguments are valid if and only if true is returned. +- virtual bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) { +- // If CurrentSrcIdx == 1, this means this function has already been called +- // once. CopyLike has one definition and one argument, thus, there is +- // nothing else to rewrite. +- if (!CopyLike.isCopy() || CurrentSrcIdx == 1) ++ virtual bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) = 0; ++ ++ /// Rewrite the current source with \p NewReg and \p NewSubReg if possible. ++ /// \return True if the rewriting was possible, false otherwise. ++ virtual bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) = 0; ++}; ++ ++/// Rewriter for COPY instructions. ++class CopyRewriter : public Rewriter { ++public: ++ CopyRewriter(MachineInstr &MI) : Rewriter(MI) { ++ assert(MI.isCopy() && "Expected copy instruction"); ++ } ++ virtual ~CopyRewriter() = default; ++ ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { ++ // CurrentSrcIdx > 0 means this function has already been called. ++ if (CurrentSrcIdx > 0) + return false; + // This is the first call to getNextRewritableSource. + // Move the CurrentSrcIdx to remember that we made that call. + CurrentSrcIdx = 1; + // The rewritable source is the argument. + const MachineOperand &MOSrc = CopyLike.getOperand(1); +- SrcReg = MOSrc.getReg(); +- SrcSubReg = MOSrc.getSubReg(); ++ Src = RegSubRegPair(MOSrc.getReg(), MOSrc.getSubReg()); + // What we track are the alternative sources of the definition. + const MachineOperand &MODef = CopyLike.getOperand(0); +- TrackReg = MODef.getReg(); +- TrackSubReg = MODef.getSubReg(); ++ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); + return true; + } + +- /// \brief Rewrite the current source with \p NewReg and \p NewSubReg +- /// if possible. +- /// \return True if the rewriting was possible, false otherwise. +- virtual bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) { +- if (!CopyLike.isCopy() || CurrentSrcIdx != 1) ++ bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) override { ++ if (CurrentSrcIdx != 1) + return false; + MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx); + MOSrc.setReg(NewReg); + MOSrc.setSubReg(NewSubReg); + return true; + } +- +- /// \brief Given a \p Def.Reg and Def.SubReg pair, use \p RewriteMap to find +- /// the new source to use for rewrite. If \p HandleMultipleSources is true and +- /// multiple sources for a given \p Def are found along the way, we found a +- /// PHI instructions that needs to be rewritten. +- /// TODO: HandleMultipleSources should be removed once we test PHI handling +- /// with coalescable copies. +- TargetInstrInfo::RegSubRegPair +- getNewSource(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, +- TargetInstrInfo::RegSubRegPair Def, +- PeepholeOptimizer::RewriteMapTy &RewriteMap, +- bool HandleMultipleSources = true) { +- TargetInstrInfo::RegSubRegPair LookupSrc(Def.Reg, Def.SubReg); +- do { +- ValueTrackerResult Res = RewriteMap.lookup(LookupSrc); +- // If there are no entries on the map, LookupSrc is the new source. +- if (!Res.isValid()) +- return LookupSrc; +- +- // There's only one source for this definition, keep searching... +- unsigned NumSrcs = Res.getNumSources(); +- if (NumSrcs == 1) { +- LookupSrc.Reg = Res.getSrcReg(0); +- LookupSrc.SubReg = Res.getSrcSubReg(0); +- continue; +- } +- +- // TODO: Remove once multiple srcs w/ coalescable copies are supported. +- if (!HandleMultipleSources) +- break; +- +- // Multiple sources, recurse into each source to find a new source +- // for it. Then, rewrite the PHI accordingly to its new edges. +- SmallVector<TargetInstrInfo::RegSubRegPair, 4> NewPHISrcs; +- for (unsigned i = 0; i < NumSrcs; ++i) { +- TargetInstrInfo::RegSubRegPair PHISrc(Res.getSrcReg(i), +- Res.getSrcSubReg(i)); +- NewPHISrcs.push_back( +- getNewSource(MRI, TII, PHISrc, RewriteMap, HandleMultipleSources)); +- } +- +- // Build the new PHI node and return its def register as the new source. +- MachineInstr *OrigPHI = const_cast<MachineInstr *>(Res.getInst()); +- MachineInstr *NewPHI = insertPHI(MRI, TII, NewPHISrcs, OrigPHI); +- DEBUG(dbgs() << "-- getNewSource\n"); +- DEBUG(dbgs() << " Replacing: " << *OrigPHI); +- DEBUG(dbgs() << " With: " << *NewPHI); +- const MachineOperand &MODef = NewPHI->getOperand(0); +- return TargetInstrInfo::RegSubRegPair(MODef.getReg(), MODef.getSubReg()); +- +- } while (true); +- +- return TargetInstrInfo::RegSubRegPair(0, 0); +- } +- +- /// \brief Rewrite the source found through \p Def, by using the \p RewriteMap +- /// and create a new COPY instruction. More info about RewriteMap in +- /// 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. +- virtual MachineInstr * +- RewriteSource(TargetInstrInfo::RegSubRegPair Def, +- PeepholeOptimizer::RewriteMapTy &RewriteMap) { +- return nullptr; +- } + }; + + /// \brief Helper class to rewrite uncoalescable copy like instructions + /// into new COPY (coalescable friendly) instructions. +-class UncoalescableRewriter : public CopyRewriter { +-protected: +- const TargetInstrInfo &TII; +- MachineRegisterInfo &MRI; +- +- /// The number of defs in the bitcast +- unsigned NumDefs; ++class UncoalescableRewriter : public Rewriter { ++ unsigned NumDefs; ///< Number of defs in the bitcast. + + public: +- UncoalescableRewriter(MachineInstr &MI, const TargetInstrInfo &TII, +- MachineRegisterInfo &MRI) +- : CopyRewriter(MI), TII(TII), MRI(MRI) { ++ UncoalescableRewriter(MachineInstr &MI) : Rewriter(MI) { + NumDefs = MI.getDesc().getNumDefs(); + } + +- /// \brief Get the next rewritable def source (TrackReg, TrackSubReg) ++ /// \see See Rewriter::getNextRewritableSource() + /// All such sources need to be considered rewritable in order to + /// rewrite a uncoalescable copy-like instruction. This method return + /// each definition that must be checked if rewritable. +- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) override { ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { + // Find the next non-dead definition and continue from there. + if (CurrentSrcIdx == NumDefs) + return false; +@@ -990,64 +886,27 @@ + } + + // What we track are the alternative sources of the definition. ++ Src = RegSubRegPair(0, 0); + const MachineOperand &MODef = CopyLike.getOperand(CurrentSrcIdx); +- TrackReg = MODef.getReg(); +- TrackSubReg = MODef.getSubReg(); ++ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); + + CurrentSrcIdx++; + return true; + } + +- /// \brief Rewrite the source found through \p Def, by using the \p RewriteMap +- /// and create a new COPY instruction. More info about RewriteMap in +- /// 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 * +- RewriteSource(TargetInstrInfo::RegSubRegPair Def, +- PeepholeOptimizer::RewriteMapTy &RewriteMap) override { +- assert(!TargetRegisterInfo::isPhysicalRegister(Def.Reg) && +- "We do not rewrite physical registers"); +- +- // Find the new source to use in the COPY rewrite. +- TargetInstrInfo::RegSubRegPair NewSrc = +- getNewSource(&MRI, &TII, Def, RewriteMap); +- +- // Insert the COPY. +- const TargetRegisterClass *DefRC = MRI.getRegClass(Def.Reg); +- unsigned NewVR = MRI.createVirtualRegister(DefRC); +- +- MachineInstr *NewCopy = +- BuildMI(*CopyLike.getParent(), &CopyLike, CopyLike.getDebugLoc(), +- TII.get(TargetOpcode::COPY), NewVR) +- .addReg(NewSrc.Reg, 0, NewSrc.SubReg); +- +- NewCopy->getOperand(0).setSubReg(Def.SubReg); +- if (Def.SubReg) +- NewCopy->getOperand(0).setIsUndef(); +- +- DEBUG(dbgs() << "-- RewriteSource\n"); +- DEBUG(dbgs() << " Replacing: " << CopyLike); +- DEBUG(dbgs() << " With: " << *NewCopy); +- MRI.replaceRegWith(Def.Reg, NewVR); +- MRI.clearKillFlags(NewVR); +- +- // We extended the lifetime of NewSrc.Reg, clear the kill flags to +- // account for that. +- MRI.clearKillFlags(NewSrc.Reg); +- +- return NewCopy; ++ bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) override { ++ return false; + } + }; + +-/// \brief Specialized rewriter for INSERT_SUBREG instruction. +-class InsertSubregRewriter : public CopyRewriter { ++/// Specialized rewriter for INSERT_SUBREG instruction. ++class InsertSubregRewriter : public Rewriter { + public: +- InsertSubregRewriter(MachineInstr &MI) : CopyRewriter(MI) { ++ InsertSubregRewriter(MachineInstr &MI) : Rewriter(MI) { + assert(MI.isInsertSubreg() && "Invalid instruction"); + } + +- /// \brief See CopyRewriter::getNextRewritableSource. ++ /// \see See Rewriter::getNextRewritableSource() + /// Here CopyLike has the following form: + /// dst = INSERT_SUBREG Src1, Src2.src2SubIdx, subIdx. + /// Src1 has the same register class has dst, hence, there is +@@ -1055,29 +914,27 @@ + /// Src2.src2SubIdx, may not be register coalescer friendly. + /// Therefore, the first call to this method returns: + /// (SrcReg, SrcSubReg) = (Src2, src2SubIdx). +- /// (TrackReg, TrackSubReg) = (dst, subIdx). ++ /// (DstReg, DstSubReg) = (dst, subIdx). + /// + /// Subsequence calls will return false. +- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) override { ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { + // If we already get the only source we can rewrite, return false. + if (CurrentSrcIdx == 2) + return false; + // We are looking at v2 = INSERT_SUBREG v0, v1, sub0. + CurrentSrcIdx = 2; + const MachineOperand &MOInsertedReg = CopyLike.getOperand(2); +- SrcReg = MOInsertedReg.getReg(); +- SrcSubReg = MOInsertedReg.getSubReg(); ++ Src = RegSubRegPair(MOInsertedReg.getReg(), MOInsertedReg.getSubReg()); + const MachineOperand &MODef = CopyLike.getOperand(0); + + // We want to track something that is compatible with the + // partial definition. +- TrackReg = MODef.getReg(); + if (MODef.getSubReg()) + // Bail if we have to compose sub-register indices. + return false; +- TrackSubReg = (unsigned)CopyLike.getOperand(3).getImm(); ++ Dst = RegSubRegPair(MODef.getReg(), ++ (unsigned)CopyLike.getOperand(3).getImm()); + return true; + } + +@@ -1092,41 +949,39 @@ + } + }; + +-/// \brief Specialized rewriter for EXTRACT_SUBREG instruction. +-class ExtractSubregRewriter : public CopyRewriter { ++/// Specialized rewriter for EXTRACT_SUBREG instruction. ++class ExtractSubregRewriter : public Rewriter { + const TargetInstrInfo &TII; + + public: + ExtractSubregRewriter(MachineInstr &MI, const TargetInstrInfo &TII) +- : CopyRewriter(MI), TII(TII) { ++ : Rewriter(MI), TII(TII) { + assert(MI.isExtractSubreg() && "Invalid instruction"); + } + +- /// \brief See CopyRewriter::getNextRewritableSource. ++ /// \see Rewriter::getNextRewritableSource() + /// Here CopyLike has the following form: + /// dst.dstSubIdx = EXTRACT_SUBREG Src, subIdx. + /// There is only one rewritable source: Src.subIdx, + /// which defines dst.dstSubIdx. +- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) override { ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { + // If we already get the only source we can rewrite, return false. + if (CurrentSrcIdx == 1) + return false; + // We are looking at v1 = EXTRACT_SUBREG v0, sub0. + CurrentSrcIdx = 1; + const MachineOperand &MOExtractedReg = CopyLike.getOperand(1); +- SrcReg = MOExtractedReg.getReg(); + // If we have to compose sub-register indices, bail out. + if (MOExtractedReg.getSubReg()) + return false; + +- SrcSubReg = 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); +- TrackReg = MODef.getReg(); +- TrackSubReg = MODef.getSubReg(); ++ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); + return true; + } + +@@ -1156,14 +1011,14 @@ + } + }; + +-/// \brief Specialized rewriter for REG_SEQUENCE instruction. +-class RegSequenceRewriter : public CopyRewriter { ++/// Specialized rewriter for REG_SEQUENCE instruction. ++class RegSequenceRewriter : public Rewriter { + public: +- RegSequenceRewriter(MachineInstr &MI) : CopyRewriter(MI) { ++ RegSequenceRewriter(MachineInstr &MI) : Rewriter(MI) { + assert(MI.isRegSequence() && "Invalid instruction"); + } + +- /// \brief See CopyRewriter::getNextRewritableSource. ++ /// \see Rewriter::getNextRewritableSource() + /// Here CopyLike has the following form: + /// dst = REG_SEQUENCE Src1.src1SubIdx, subIdx1, Src2.src2SubIdx, subIdx2. + /// Each call will return a different source, walking all the available +@@ -1171,17 +1026,16 @@ + /// + /// The first call returns: + /// (SrcReg, SrcSubReg) = (Src1, src1SubIdx). +- /// (TrackReg, TrackSubReg) = (dst, subIdx1). ++ /// (DstReg, DstSubReg) = (dst, subIdx1). + /// + /// The second call returns: + /// (SrcReg, SrcSubReg) = (Src2, src2SubIdx). +- /// (TrackReg, TrackSubReg) = (dst, subIdx2). ++ /// (DstReg, DstSubReg) = (dst, subIdx2). + /// + /// And so on, until all the sources have been traversed, then + /// it returns false. +- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, +- unsigned &TrackReg, +- unsigned &TrackSubReg) override { ++ bool getNextRewritableSource(RegSubRegPair &Src, ++ RegSubRegPair &Dst) override { + // We are looking at v0 = REG_SEQUENCE v1, sub1, v2, sub2, etc. + + // If this is the first call, move to the first argument. +@@ -1194,17 +1048,17 @@ + return false; + } + const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx); +- SrcReg = MOInsertedReg.getReg(); ++ Src.Reg = MOInsertedReg.getReg(); + // If we have to compose sub-register indices, bail out. +- if ((SrcSubReg = MOInsertedReg.getSubReg())) ++ if ((Src.SubReg = MOInsertedReg.getSubReg())) + return false; + + // We want to track something that is compatible with the related + // partial definition. +- TrackSubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm(); ++ Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm(); + + const MachineOperand &MODef = CopyLike.getOperand(0); +- TrackReg = MODef.getReg(); ++ Dst.Reg = MODef.getReg(); + // If we have to compose sub-registers, bail. + return MODef.getSubReg() == 0; + } +@@ -1224,16 +1078,14 @@ + + } // end anonymous namespace + +-/// \brief Get the appropriated CopyRewriter for \p MI. +-/// \return A pointer to a dynamically allocated CopyRewriter or nullptr +-/// if no rewriter works for \p MI. +-static CopyRewriter *getCopyRewriter(MachineInstr &MI, +- const TargetInstrInfo &TII, +- MachineRegisterInfo &MRI) { ++/// Get the appropriated Rewriter for \p MI. *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805151750.w4FHoJI1094520>