diff options
author | paperchalice <liujunchang97@outlook.com> | 2024-07-15 15:11:06 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-15 15:11:06 +0800 |
commit | 01191874f9011d3ce8b7c2830ece1f030c60da7f (patch) | |
tree | e8fc047894bbb7d750a609c7087268396e6fd2c0 /llvm/lib/CodeGen/TwoAddressInstructionPass.cpp | |
parent | caa0e42ceb6e671d68b8b8e1d04f136696a4228b (diff) | |
download | llvm-01191874f9011d3ce8b7c2830ece1f030c60da7f.zip llvm-01191874f9011d3ce8b7c2830ece1f030c60da7f.tar.gz llvm-01191874f9011d3ce8b7c2830ece1f030c60da7f.tar.bz2 |
[CodeGen] Port `two-address-instructions` to new pass manager (#98632)
Add `TwoAddressInstructionPass`.
Diffstat (limited to 'llvm/lib/CodeGen/TwoAddressInstructionPass.cpp')
-rw-r--r-- | llvm/lib/CodeGen/TwoAddressInstructionPass.cpp | 190 |
1 files changed, 120 insertions, 70 deletions
diff --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp index 73385fe..665d578 100644 --- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -26,6 +26,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/TwoAddressInstructionPass.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -36,10 +37,12 @@ #include "llvm/CodeGen/LiveIntervals.h" #include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" @@ -86,7 +89,7 @@ static cl::opt<unsigned> MaxDataFlowEdge( namespace { -class TwoAddressInstructionPass : public MachineFunctionPass { +class TwoAddressInstructionImpl { MachineFunction *MF = nullptr; const TargetInstrInfo *TII = nullptr; const TargetRegisterInfo *TRI = nullptr; @@ -186,10 +189,30 @@ class TwoAddressInstructionPass : public MachineFunctionPass { bool processStatepoint(MachineInstr *MI, TiedOperandMap &TiedOperands); public: + TwoAddressInstructionImpl(MachineFunction &MF, MachineFunctionPass *P); + TwoAddressInstructionImpl(MachineFunction &MF, + MachineFunctionAnalysisManager &MFAM); + void setOptLevel(CodeGenOptLevel Level) { OptLevel = Level; } + bool run(); +}; + +class TwoAddressInstructionLegacyPass : public MachineFunctionPass { +public: static char ID; // Pass identification, replacement for typeid - TwoAddressInstructionPass() : MachineFunctionPass(ID) { - initializeTwoAddressInstructionPassPass(*PassRegistry::getPassRegistry()); + TwoAddressInstructionLegacyPass() : MachineFunctionPass(ID) { + initializeTwoAddressInstructionLegacyPassPass( + *PassRegistry::getPassRegistry()); + } + + /// Pass entry point. + bool runOnMachineFunction(MachineFunction &MF) override { + TwoAddressInstructionImpl Impl(MF, this); + // Disable optimizations if requested. We cannot skip the whole pass as some + // fixups are necessary for correctness. + if (skipFunction(MF.getFunction())) + Impl.setOptLevel(CodeGenOptLevel::None); + return Impl.run(); } void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -203,26 +226,76 @@ public: AU.addPreservedID(MachineDominatorsID); MachineFunctionPass::getAnalysisUsage(AU); } - - /// Pass entry point. - bool runOnMachineFunction(MachineFunction&) override; }; } // end anonymous namespace -char TwoAddressInstructionPass::ID = 0; +PreservedAnalyses +TwoAddressInstructionPass::run(MachineFunction &MF, + MachineFunctionAnalysisManager &MFAM) { + // Disable optimizations if requested. We cannot skip the whole pass as some + // fixups are necessary for correctness. + TwoAddressInstructionImpl Impl(MF, MFAM); + if (MF.getFunction().hasOptNone()) + Impl.setOptLevel(CodeGenOptLevel::None); + + MFPropsModifier _(*this, MF); + bool Changed = Impl.run(); + if (!Changed) + return PreservedAnalyses::all(); + auto PA = getMachineFunctionPassPreservedAnalyses(); + PA.preserve<LiveIntervalsAnalysis>(); + PA.preserve<LiveVariablesAnalysis>(); + PA.preserve<MachineDominatorTreeAnalysis>(); + PA.preserve<MachineLoopAnalysis>(); + PA.preserve<SlotIndexesAnalysis>(); + PA.preserveSet<CFGAnalyses>(); + return PA; +} + +char TwoAddressInstructionLegacyPass::ID = 0; -char &llvm::TwoAddressInstructionPassID = TwoAddressInstructionPass::ID; +char &llvm::TwoAddressInstructionPassID = TwoAddressInstructionLegacyPass::ID; -INITIALIZE_PASS_BEGIN(TwoAddressInstructionPass, DEBUG_TYPE, - "Two-Address instruction pass", false, false) +INITIALIZE_PASS_BEGIN(TwoAddressInstructionLegacyPass, DEBUG_TYPE, + "Two-Address instruction pass", false, false) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_END(TwoAddressInstructionPass, DEBUG_TYPE, - "Two-Address instruction pass", false, false) +INITIALIZE_PASS_END(TwoAddressInstructionLegacyPass, DEBUG_TYPE, + "Two-Address instruction pass", false, false) + +TwoAddressInstructionImpl::TwoAddressInstructionImpl( + MachineFunction &Func, MachineFunctionAnalysisManager &MFAM) + : MF(&Func), TII(Func.getSubtarget().getInstrInfo()), + TRI(Func.getSubtarget().getRegisterInfo()), + InstrItins(Func.getSubtarget().getInstrItineraryData()), + MRI(&Func.getRegInfo()), + LV(MFAM.getCachedResult<LiveVariablesAnalysis>(Func)), + LIS(MFAM.getCachedResult<LiveIntervalsAnalysis>(Func)), + OptLevel(Func.getTarget().getOptLevel()) { + auto &FAM = MFAM.getResult<FunctionAnalysisManagerMachineFunctionProxy>(Func) + .getManager(); + AA = FAM.getCachedResult<AAManager>(Func.getFunction()); +} + +TwoAddressInstructionImpl::TwoAddressInstructionImpl(MachineFunction &Func, + MachineFunctionPass *P) + : MF(&Func), TII(Func.getSubtarget().getInstrInfo()), + TRI(Func.getSubtarget().getRegisterInfo()), + InstrItins(Func.getSubtarget().getInstrItineraryData()), + MRI(&Func.getRegInfo()), OptLevel(Func.getTarget().getOptLevel()) { + auto *LVWrapper = P->getAnalysisIfAvailable<LiveVariablesWrapperPass>(); + LV = LVWrapper ? &LVWrapper->getLV() : nullptr; + auto *LISWrapper = P->getAnalysisIfAvailable<LiveIntervalsWrapperPass>(); + LIS = LISWrapper ? &LISWrapper->getLIS() : nullptr; + if (auto *AAPass = P->getAnalysisIfAvailable<AAResultsWrapperPass>()) + AA = &AAPass->getAAResults(); + else + AA = nullptr; +} /// Return the MachineInstr* if it is the single def of the Reg in current BB. MachineInstr * -TwoAddressInstructionPass::getSingleDef(Register Reg, +TwoAddressInstructionImpl::getSingleDef(Register Reg, MachineBasicBlock *BB) const { MachineInstr *Ret = nullptr; for (MachineInstr &DefMI : MRI->def_instructions(Reg)) { @@ -243,7 +316,7 @@ TwoAddressInstructionPass::getSingleDef(Register Reg, /// %Tmp2 = copy %ToReg; /// MaxLen specifies the maximum length of the copy chain the func /// can walk through. -bool TwoAddressInstructionPass::isRevCopyChain(Register FromReg, Register ToReg, +bool TwoAddressInstructionImpl::isRevCopyChain(Register FromReg, Register ToReg, int Maxlen) { Register TmpReg = FromReg; for (int i = 0; i < Maxlen; i++) { @@ -263,7 +336,7 @@ bool TwoAddressInstructionPass::isRevCopyChain(Register FromReg, Register ToReg, /// in the MBB that defines the specified register and the two-address /// instruction which is being processed. It also returns the last def location /// by reference. -bool TwoAddressInstructionPass::noUseAfterLastDef(Register Reg, unsigned Dist, +bool TwoAddressInstructionImpl::noUseAfterLastDef(Register Reg, unsigned Dist, unsigned &LastDef) { LastDef = 0; unsigned LastUse = Dist; @@ -286,7 +359,7 @@ bool TwoAddressInstructionPass::noUseAfterLastDef(Register Reg, unsigned Dist, /// Return true if the specified MI is a copy instruction or an extract_subreg /// instruction. It also returns the source and destination registers and /// whether they are physical registers by reference. -bool TwoAddressInstructionPass::isCopyToReg(MachineInstr &MI, Register &SrcReg, +bool TwoAddressInstructionImpl::isCopyToReg(MachineInstr &MI, Register &SrcReg, Register &DstReg, bool &IsSrcPhys, bool &IsDstPhys) const { SrcReg = 0; @@ -306,7 +379,7 @@ bool TwoAddressInstructionPass::isCopyToReg(MachineInstr &MI, Register &SrcReg, return true; } -bool TwoAddressInstructionPass::isPlainlyKilled(const MachineInstr *MI, +bool TwoAddressInstructionImpl::isPlainlyKilled(const MachineInstr *MI, LiveRange &LR) const { // This is to match the kill flag version where undefs don't have kill flags. if (!LR.hasAtLeastOneValue()) @@ -320,7 +393,7 @@ bool TwoAddressInstructionPass::isPlainlyKilled(const MachineInstr *MI, /// Test if the given register value, which is used by the /// given instruction, is killed by the given instruction. -bool TwoAddressInstructionPass::isPlainlyKilled(const MachineInstr *MI, +bool TwoAddressInstructionImpl::isPlainlyKilled(const MachineInstr *MI, Register Reg) const { // FIXME: Sometimes tryInstructionTransform() will add instructions and // test whether they can be folded before keeping them. In this case it @@ -344,7 +417,7 @@ bool TwoAddressInstructionPass::isPlainlyKilled(const MachineInstr *MI, /// Test if the register used by the given operand is killed by the operand's /// instruction. -bool TwoAddressInstructionPass::isPlainlyKilled( +bool TwoAddressInstructionImpl::isPlainlyKilled( const MachineOperand &MO) const { return MO.isKill() || isPlainlyKilled(MO.getParent(), MO.getReg()); } @@ -366,7 +439,7 @@ bool TwoAddressInstructionPass::isPlainlyKilled( /// /// If allowFalsePositives is true then likely kills are treated as kills even /// if it can't be proven that they are kills. -bool TwoAddressInstructionPass::isKilled(MachineInstr &MI, Register Reg, +bool TwoAddressInstructionImpl::isKilled(MachineInstr &MI, Register Reg, bool allowFalsePositives) const { MachineInstr *DefMI = &MI; while (true) { @@ -411,7 +484,7 @@ static bool isTwoAddrUse(MachineInstr &MI, Register Reg, Register &DstReg) { /// Given a register, if all its uses are in the same basic block, return the /// last use instruction if it's a copy or a two-address use. -MachineInstr *TwoAddressInstructionPass::findOnlyInterestingUse( +MachineInstr *TwoAddressInstructionImpl::findOnlyInterestingUse( Register Reg, MachineBasicBlock *MBB, bool &IsCopy, Register &DstReg, bool &IsDstPhys) const { MachineOperand *UseOp = nullptr; @@ -468,7 +541,7 @@ static MCRegister getMappedReg(Register Reg, } /// Return true if the two registers are equal or aliased. -bool TwoAddressInstructionPass::regsAreCompatible(Register RegA, +bool TwoAddressInstructionImpl::regsAreCompatible(Register RegA, Register RegB) const { if (RegA == RegB) return true; @@ -478,7 +551,7 @@ bool TwoAddressInstructionPass::regsAreCompatible(Register RegA, } /// From RegMap remove entries mapped to a physical register which overlaps MO. -void TwoAddressInstructionPass::removeMapRegEntry( +void TwoAddressInstructionImpl::removeMapRegEntry( const MachineOperand &MO, DenseMap<Register, Register> &RegMap) const { assert( (MO.isReg() || MO.isRegMask()) && @@ -510,7 +583,7 @@ void TwoAddressInstructionPass::removeMapRegEntry( /// /// After the MUL instruction, $rdx contains different value than in the COPY /// instruction. So %2 should not map to $rdx after MUL. -void TwoAddressInstructionPass::removeClobberedSrcRegMap(MachineInstr *MI) { +void TwoAddressInstructionImpl::removeClobberedSrcRegMap(MachineInstr *MI) { if (MI->isCopy()) { // If a virtual register is copied to its mapped physical register, it // doesn't change the potential coalescing between them, so we don't remove @@ -546,7 +619,7 @@ void TwoAddressInstructionPass::removeClobberedSrcRegMap(MachineInstr *MI) { } // Returns true if Reg is equal or aliased to at least one register in Set. -bool TwoAddressInstructionPass::regOverlapsSet( +bool TwoAddressInstructionImpl::regOverlapsSet( const SmallVectorImpl<Register> &Set, Register Reg) const { for (unsigned R : Set) if (TRI->regsOverlap(R, Reg)) @@ -557,7 +630,7 @@ bool TwoAddressInstructionPass::regOverlapsSet( /// Return true if it's potentially profitable to commute the two-address /// instruction that's being processed. -bool TwoAddressInstructionPass::isProfitableToCommute(Register RegA, +bool TwoAddressInstructionImpl::isProfitableToCommute(Register RegA, Register RegB, Register RegC, MachineInstr *MI, @@ -662,7 +735,7 @@ bool TwoAddressInstructionPass::isProfitableToCommute(Register RegA, /// Commute a two-address instruction and update the basic block, distance map, /// and live variables if needed. Return true if it is successful. -bool TwoAddressInstructionPass::commuteInstruction(MachineInstr *MI, +bool TwoAddressInstructionImpl::commuteInstruction(MachineInstr *MI, unsigned DstIdx, unsigned RegBIdx, unsigned RegCIdx, @@ -693,7 +766,7 @@ bool TwoAddressInstructionPass::commuteInstruction(MachineInstr *MI, /// Return true if it is profitable to convert the given 2-address instruction /// to a 3-address one. -bool TwoAddressInstructionPass::isProfitableToConv3Addr(Register RegA, +bool TwoAddressInstructionImpl::isProfitableToConv3Addr(Register RegA, Register RegB) { // Look for situations like this: // %reg1024 = MOV r1 @@ -710,7 +783,7 @@ bool TwoAddressInstructionPass::isProfitableToConv3Addr(Register RegA, /// Convert the specified two-address instruction into a three address one. /// Return true if this transformation was successful. -bool TwoAddressInstructionPass::convertInstTo3Addr( +bool TwoAddressInstructionImpl::convertInstTo3Addr( MachineBasicBlock::iterator &mi, MachineBasicBlock::iterator &nmi, Register RegA, Register RegB, unsigned &Dist) { MachineInstrSpan MIS(mi, MBB); @@ -752,7 +825,7 @@ bool TwoAddressInstructionPass::convertInstTo3Addr( /// Scan forward recursively for only uses, update maps if the use is a copy or /// a two-address instruction. -void TwoAddressInstructionPass::scanUses(Register DstReg) { +void TwoAddressInstructionImpl::scanUses(Register DstReg) { SmallVector<Register, 4> VirtRegPairs; bool IsDstPhys; bool IsCopy = false; @@ -805,7 +878,7 @@ void TwoAddressInstructionPass::scanUses(Register DstReg) { /// coalesced to r0 (from the input side). v1025 is mapped to r1. v1026 is /// potentially joined with r1 on the output side. It's worthwhile to commute /// 'add' to eliminate a copy. -void TwoAddressInstructionPass::processCopy(MachineInstr *MI) { +void TwoAddressInstructionImpl::processCopy(MachineInstr *MI) { if (Processed.count(MI)) return; @@ -831,7 +904,7 @@ void TwoAddressInstructionPass::processCopy(MachineInstr *MI) { /// If there is one more local instruction that reads 'Reg' and it kills 'Reg, /// consider moving the instruction below the kill instruction in order to /// eliminate the need for the copy. -bool TwoAddressInstructionPass::rescheduleMIBelowKill( +bool TwoAddressInstructionImpl::rescheduleMIBelowKill( MachineBasicBlock::iterator &mi, MachineBasicBlock::iterator &nmi, Register Reg) { // Bail immediately if we don't have LV or LIS available. We use them to find @@ -998,7 +1071,7 @@ bool TwoAddressInstructionPass::rescheduleMIBelowKill( /// Return true if the re-scheduling will put the given instruction too close /// to the defs of its register dependencies. -bool TwoAddressInstructionPass::isDefTooClose(Register Reg, unsigned Dist, +bool TwoAddressInstructionImpl::isDefTooClose(Register Reg, unsigned Dist, MachineInstr *MI) { for (MachineInstr &DefMI : MRI->def_instructions(Reg)) { if (DefMI.getParent() != MBB || DefMI.isCopy() || DefMI.isCopyLike()) @@ -1019,7 +1092,7 @@ bool TwoAddressInstructionPass::isDefTooClose(Register Reg, unsigned Dist, /// If there is one more local instruction that reads 'Reg' and it kills 'Reg, /// consider moving the kill instruction above the current two-address /// instruction in order to eliminate the need for the copy. -bool TwoAddressInstructionPass::rescheduleKillAboveMI( +bool TwoAddressInstructionImpl::rescheduleKillAboveMI( MachineBasicBlock::iterator &mi, MachineBasicBlock::iterator &nmi, Register Reg) { // Bail immediately if we don't have LV or LIS available. We use them to find @@ -1171,7 +1244,7 @@ bool TwoAddressInstructionPass::rescheduleKillAboveMI( /// to commute operands in the instruction. /// /// Returns true if the transformation happened. Otherwise, returns false. -bool TwoAddressInstructionPass::tryInstructionCommute(MachineInstr *MI, +bool TwoAddressInstructionImpl::tryInstructionCommute(MachineInstr *MI, unsigned DstOpIdx, unsigned BaseOpIdx, bool BaseOpKilled, @@ -1236,11 +1309,9 @@ bool TwoAddressInstructionPass::tryInstructionCommute(MachineInstr *MI, /// (either because they were untied, or because mi was rescheduled, and will /// be visited again later). If the shouldOnlyCommute flag is true, only /// instruction commutation is attempted. -bool TwoAddressInstructionPass:: -tryInstructionTransform(MachineBasicBlock::iterator &mi, - MachineBasicBlock::iterator &nmi, - unsigned SrcIdx, unsigned DstIdx, - unsigned &Dist, bool shouldOnlyCommute) { +bool TwoAddressInstructionImpl::tryInstructionTransform( + MachineBasicBlock::iterator &mi, MachineBasicBlock::iterator &nmi, + unsigned SrcIdx, unsigned DstIdx, unsigned &Dist, bool shouldOnlyCommute) { if (OptLevel == CodeGenOptLevel::None) return false; @@ -1440,8 +1511,8 @@ tryInstructionTransform(MachineBasicBlock::iterator &mi, // Collect tied operands of MI that need to be handled. // Rewrite trivial cases immediately. // Return true if any tied operands where found, including the trivial ones. -bool TwoAddressInstructionPass:: -collectTiedOperands(MachineInstr *MI, TiedOperandMap &TiedOperands) { +bool TwoAddressInstructionImpl::collectTiedOperands( + MachineInstr *MI, TiedOperandMap &TiedOperands) { bool AnyOps = false; unsigned NumOps = MI->getNumOperands(); @@ -1479,10 +1550,9 @@ collectTiedOperands(MachineInstr *MI, TiedOperandMap &TiedOperands) { // Process a list of tied MI operands that all use the same source register. // The tied pairs are of the form (SrcIdx, DstIdx). -void -TwoAddressInstructionPass::processTiedPairs(MachineInstr *MI, - TiedPairList &TiedPairs, - unsigned &Dist) { +void TwoAddressInstructionImpl::processTiedPairs(MachineInstr *MI, + TiedPairList &TiedPairs, + unsigned &Dist) { bool IsEarlyClobber = llvm::any_of(TiedPairs, [MI](auto const &TP) { return MI->getOperand(TP.second).isEarlyClobber(); }); @@ -1668,7 +1738,7 @@ TwoAddressInstructionPass::processTiedPairs(MachineInstr *MI, // and replaces all uses of RegA with RegB. // No extra COPY instruction is necessary because tied use is killed at // STATEPOINT. -bool TwoAddressInstructionPass::processStatepoint( +bool TwoAddressInstructionImpl::processStatepoint( MachineInstr *MI, TiedOperandMap &TiedOperands) { bool NeedCopy = false; @@ -1755,27 +1825,7 @@ bool TwoAddressInstructionPass::processStatepoint( } /// Reduce two-address instructions to two operands. -bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) { - MF = &Func; - const TargetMachine &TM = MF->getTarget(); - MRI = &MF->getRegInfo(); - TII = MF->getSubtarget().getInstrInfo(); - TRI = MF->getSubtarget().getRegisterInfo(); - InstrItins = MF->getSubtarget().getInstrItineraryData(); - auto *LVWrapper = getAnalysisIfAvailable<LiveVariablesWrapperPass>(); - LV = LVWrapper ? &LVWrapper->getLV() : nullptr; - auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>(); - LIS = LISWrapper ? &LISWrapper->getLIS() : nullptr; - if (auto *AAPass = getAnalysisIfAvailable<AAResultsWrapperPass>()) - AA = &AAPass->getAAResults(); - else - AA = nullptr; - OptLevel = TM.getOptLevel(); - // Disable optimizations if requested. We cannot skip the whole pass as some - // fixups are necessary for correctness. - if (skipFunction(Func.getFunction())) - OptLevel = CodeGenOptLevel::None; - +bool TwoAddressInstructionImpl::run() { bool MadeChange = false; LLVM_DEBUG(dbgs() << "********** REWRITING TWO-ADDR INSTRS **********\n"); @@ -1930,8 +1980,8 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) { /// /// undef %dst:ssub0 = COPY %v1 /// %dst:ssub1 = COPY %v2 -void TwoAddressInstructionPass:: -eliminateRegSequence(MachineBasicBlock::iterator &MBBI) { +void TwoAddressInstructionImpl::eliminateRegSequence( + MachineBasicBlock::iterator &MBBI) { MachineInstr &MI = *MBBI; Register DstReg = MI.getOperand(0).getReg(); |