109467b48Spatrick //===- MachineCopyPropagation.cpp - Machine Copy Propagation Pass ---------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This is an extremely simple MachineInstr-level copy propagation pass.
1009467b48Spatrick //
1109467b48Spatrick // This pass forwards the source of COPYs to the users of their destinations
1209467b48Spatrick // when doing so is legal. For example:
1309467b48Spatrick //
1409467b48Spatrick // %reg1 = COPY %reg0
1509467b48Spatrick // ...
1609467b48Spatrick // ... = OP %reg1
1709467b48Spatrick //
1809467b48Spatrick // If
1909467b48Spatrick // - %reg0 has not been clobbered by the time of the use of %reg1
2009467b48Spatrick // - the register class constraints are satisfied
2109467b48Spatrick // - the COPY def is the only value that reaches OP
2209467b48Spatrick // then this pass replaces the above with:
2309467b48Spatrick //
2409467b48Spatrick // %reg1 = COPY %reg0
2509467b48Spatrick // ...
2609467b48Spatrick // ... = OP %reg0
2709467b48Spatrick //
2809467b48Spatrick // This pass also removes some redundant COPYs. For example:
2909467b48Spatrick //
3009467b48Spatrick // %R1 = COPY %R0
3109467b48Spatrick // ... // No clobber of %R1
3209467b48Spatrick // %R0 = COPY %R1 <<< Removed
3309467b48Spatrick //
3409467b48Spatrick // or
3509467b48Spatrick //
3609467b48Spatrick // %R1 = COPY %R0
3709467b48Spatrick // ... // No clobber of %R0
3809467b48Spatrick // %R1 = COPY %R0 <<< Removed
3909467b48Spatrick //
4009467b48Spatrick // or
4109467b48Spatrick //
4209467b48Spatrick // $R0 = OP ...
4309467b48Spatrick // ... // No read/clobber of $R0 and $R1
4409467b48Spatrick // $R1 = COPY $R0 // $R0 is killed
4509467b48Spatrick // Replace $R0 with $R1 and remove the COPY
4609467b48Spatrick // $R1 = OP ...
4709467b48Spatrick // ...
4809467b48Spatrick //
4909467b48Spatrick //===----------------------------------------------------------------------===//
5009467b48Spatrick
5109467b48Spatrick #include "llvm/ADT/DenseMap.h"
5209467b48Spatrick #include "llvm/ADT/STLExtras.h"
5309467b48Spatrick #include "llvm/ADT/SetVector.h"
54097a140dSpatrick #include "llvm/ADT/SmallSet.h"
5509467b48Spatrick #include "llvm/ADT/SmallVector.h"
5609467b48Spatrick #include "llvm/ADT/Statistic.h"
5709467b48Spatrick #include "llvm/ADT/iterator_range.h"
5809467b48Spatrick #include "llvm/CodeGen/MachineBasicBlock.h"
5909467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
6009467b48Spatrick #include "llvm/CodeGen/MachineFunctionPass.h"
6109467b48Spatrick #include "llvm/CodeGen/MachineInstr.h"
6209467b48Spatrick #include "llvm/CodeGen/MachineOperand.h"
6309467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
6409467b48Spatrick #include "llvm/CodeGen/TargetInstrInfo.h"
6509467b48Spatrick #include "llvm/CodeGen/TargetRegisterInfo.h"
6609467b48Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
6709467b48Spatrick #include "llvm/InitializePasses.h"
6809467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
6909467b48Spatrick #include "llvm/Pass.h"
7009467b48Spatrick #include "llvm/Support/Debug.h"
7109467b48Spatrick #include "llvm/Support/DebugCounter.h"
7209467b48Spatrick #include "llvm/Support/raw_ostream.h"
7309467b48Spatrick #include <cassert>
7409467b48Spatrick #include <iterator>
7509467b48Spatrick
7609467b48Spatrick using namespace llvm;
7709467b48Spatrick
7809467b48Spatrick #define DEBUG_TYPE "machine-cp"
7909467b48Spatrick
8009467b48Spatrick STATISTIC(NumDeletes, "Number of dead copies deleted");
8109467b48Spatrick STATISTIC(NumCopyForwards, "Number of copy uses forwarded");
8209467b48Spatrick STATISTIC(NumCopyBackwardPropagated, "Number of copy defs backward propagated");
8309467b48Spatrick DEBUG_COUNTER(FwdCounter, "machine-cp-fwd",
8409467b48Spatrick "Controls which register COPYs are forwarded");
8509467b48Spatrick
86*d415bd75Srobert static cl::opt<bool> MCPUseCopyInstr("mcp-use-is-copy-instr", cl::init(false),
87*d415bd75Srobert cl::Hidden);
88*d415bd75Srobert
8909467b48Spatrick namespace {
9009467b48Spatrick
isCopyInstr(const MachineInstr & MI,const TargetInstrInfo & TII,bool UseCopyInstr)91*d415bd75Srobert static std::optional<DestSourcePair> isCopyInstr(const MachineInstr &MI,
92*d415bd75Srobert const TargetInstrInfo &TII,
93*d415bd75Srobert bool UseCopyInstr) {
94*d415bd75Srobert if (UseCopyInstr)
95*d415bd75Srobert return TII.isCopyInstr(MI);
96*d415bd75Srobert
97*d415bd75Srobert if (MI.isCopy())
98*d415bd75Srobert return std::optional<DestSourcePair>(
99*d415bd75Srobert DestSourcePair{MI.getOperand(0), MI.getOperand(1)});
100*d415bd75Srobert
101*d415bd75Srobert return std::nullopt;
102*d415bd75Srobert }
103*d415bd75Srobert
10409467b48Spatrick class CopyTracker {
10509467b48Spatrick struct CopyInfo {
10609467b48Spatrick MachineInstr *MI;
10773471bf0Spatrick SmallVector<MCRegister, 4> DefRegs;
10809467b48Spatrick bool Avail;
10909467b48Spatrick };
11009467b48Spatrick
11173471bf0Spatrick DenseMap<MCRegister, CopyInfo> Copies;
11209467b48Spatrick
11309467b48Spatrick public:
11409467b48Spatrick /// Mark all of the given registers and their subregisters as unavailable for
11509467b48Spatrick /// copying.
markRegsUnavailable(ArrayRef<MCRegister> Regs,const TargetRegisterInfo & TRI)11673471bf0Spatrick void markRegsUnavailable(ArrayRef<MCRegister> Regs,
11709467b48Spatrick const TargetRegisterInfo &TRI) {
11873471bf0Spatrick for (MCRegister Reg : Regs) {
11909467b48Spatrick // Source of copy is no longer available for propagation.
12009467b48Spatrick for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
12109467b48Spatrick auto CI = Copies.find(*RUI);
12209467b48Spatrick if (CI != Copies.end())
12309467b48Spatrick CI->second.Avail = false;
12409467b48Spatrick }
12509467b48Spatrick }
12609467b48Spatrick }
12709467b48Spatrick
12809467b48Spatrick /// Remove register from copy maps.
invalidateRegister(MCRegister Reg,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)129*d415bd75Srobert void invalidateRegister(MCRegister Reg, const TargetRegisterInfo &TRI,
130*d415bd75Srobert const TargetInstrInfo &TII, bool UseCopyInstr) {
13109467b48Spatrick // Since Reg might be a subreg of some registers, only invalidate Reg is not
13209467b48Spatrick // enough. We have to find the COPY defines Reg or registers defined by Reg
13309467b48Spatrick // and invalidate all of them.
13473471bf0Spatrick SmallSet<MCRegister, 8> RegsToInvalidate;
135097a140dSpatrick RegsToInvalidate.insert(Reg);
13609467b48Spatrick for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
13709467b48Spatrick auto I = Copies.find(*RUI);
13809467b48Spatrick if (I != Copies.end()) {
13909467b48Spatrick if (MachineInstr *MI = I->second.MI) {
140*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
141*d415bd75Srobert isCopyInstr(*MI, TII, UseCopyInstr);
142*d415bd75Srobert assert(CopyOperands && "Expect copy");
143*d415bd75Srobert
144*d415bd75Srobert RegsToInvalidate.insert(
145*d415bd75Srobert CopyOperands->Destination->getReg().asMCReg());
146*d415bd75Srobert RegsToInvalidate.insert(CopyOperands->Source->getReg().asMCReg());
14709467b48Spatrick }
14809467b48Spatrick RegsToInvalidate.insert(I->second.DefRegs.begin(),
14909467b48Spatrick I->second.DefRegs.end());
15009467b48Spatrick }
15109467b48Spatrick }
15273471bf0Spatrick for (MCRegister InvalidReg : RegsToInvalidate)
15309467b48Spatrick for (MCRegUnitIterator RUI(InvalidReg, &TRI); RUI.isValid(); ++RUI)
15409467b48Spatrick Copies.erase(*RUI);
15509467b48Spatrick }
15609467b48Spatrick
15709467b48Spatrick /// Clobber a single register, removing it from the tracker's copy maps.
clobberRegister(MCRegister Reg,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)158*d415bd75Srobert void clobberRegister(MCRegister Reg, const TargetRegisterInfo &TRI,
159*d415bd75Srobert const TargetInstrInfo &TII, bool UseCopyInstr) {
16009467b48Spatrick for (MCRegUnitIterator RUI(Reg, &TRI); RUI.isValid(); ++RUI) {
16109467b48Spatrick auto I = Copies.find(*RUI);
16209467b48Spatrick if (I != Copies.end()) {
16309467b48Spatrick // When we clobber the source of a copy, we need to clobber everything
16409467b48Spatrick // it defined.
16509467b48Spatrick markRegsUnavailable(I->second.DefRegs, TRI);
16609467b48Spatrick // When we clobber the destination of a copy, we need to clobber the
16709467b48Spatrick // whole register it defined.
168*d415bd75Srobert if (MachineInstr *MI = I->second.MI) {
169*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
170*d415bd75Srobert isCopyInstr(*MI, TII, UseCopyInstr);
171*d415bd75Srobert markRegsUnavailable({CopyOperands->Destination->getReg().asMCReg()},
172*d415bd75Srobert TRI);
173*d415bd75Srobert }
17409467b48Spatrick // Now we can erase the copy.
17509467b48Spatrick Copies.erase(I);
17609467b48Spatrick }
17709467b48Spatrick }
17809467b48Spatrick }
17909467b48Spatrick
18009467b48Spatrick /// Add this copy's registers into the tracker's copy maps.
trackCopy(MachineInstr * MI,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)181*d415bd75Srobert void trackCopy(MachineInstr *MI, const TargetRegisterInfo &TRI,
182*d415bd75Srobert const TargetInstrInfo &TII, bool UseCopyInstr) {
183*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
184*d415bd75Srobert isCopyInstr(*MI, TII, UseCopyInstr);
185*d415bd75Srobert assert(CopyOperands && "Tracking non-copy?");
18609467b48Spatrick
187*d415bd75Srobert MCRegister Src = CopyOperands->Source->getReg().asMCReg();
188*d415bd75Srobert MCRegister Def = CopyOperands->Destination->getReg().asMCReg();
18909467b48Spatrick
19009467b48Spatrick // Remember Def is defined by the copy.
19109467b48Spatrick for (MCRegUnitIterator RUI(Def, &TRI); RUI.isValid(); ++RUI)
19209467b48Spatrick Copies[*RUI] = {MI, {}, true};
19309467b48Spatrick
19409467b48Spatrick // Remember source that's copied to Def. Once it's clobbered, then
19509467b48Spatrick // it's no longer available for copy propagation.
19609467b48Spatrick for (MCRegUnitIterator RUI(Src, &TRI); RUI.isValid(); ++RUI) {
19709467b48Spatrick auto I = Copies.insert({*RUI, {nullptr, {}, false}});
19809467b48Spatrick auto &Copy = I.first->second;
19909467b48Spatrick if (!is_contained(Copy.DefRegs, Def))
20009467b48Spatrick Copy.DefRegs.push_back(Def);
20109467b48Spatrick }
20209467b48Spatrick }
20309467b48Spatrick
hasAnyCopies()20409467b48Spatrick bool hasAnyCopies() {
20509467b48Spatrick return !Copies.empty();
20609467b48Spatrick }
20709467b48Spatrick
findCopyForUnit(MCRegister RegUnit,const TargetRegisterInfo & TRI,bool MustBeAvailable=false)20873471bf0Spatrick MachineInstr *findCopyForUnit(MCRegister RegUnit,
20973471bf0Spatrick const TargetRegisterInfo &TRI,
21009467b48Spatrick bool MustBeAvailable = false) {
21109467b48Spatrick auto CI = Copies.find(RegUnit);
21209467b48Spatrick if (CI == Copies.end())
21309467b48Spatrick return nullptr;
21409467b48Spatrick if (MustBeAvailable && !CI->second.Avail)
21509467b48Spatrick return nullptr;
21609467b48Spatrick return CI->second.MI;
21709467b48Spatrick }
21809467b48Spatrick
findCopyDefViaUnit(MCRegister RegUnit,const TargetRegisterInfo & TRI)21973471bf0Spatrick MachineInstr *findCopyDefViaUnit(MCRegister RegUnit,
22009467b48Spatrick const TargetRegisterInfo &TRI) {
22109467b48Spatrick auto CI = Copies.find(RegUnit);
22209467b48Spatrick if (CI == Copies.end())
22309467b48Spatrick return nullptr;
22409467b48Spatrick if (CI->second.DefRegs.size() != 1)
22509467b48Spatrick return nullptr;
22609467b48Spatrick MCRegUnitIterator RUI(CI->second.DefRegs[0], &TRI);
22709467b48Spatrick return findCopyForUnit(*RUI, TRI, true);
22809467b48Spatrick }
22909467b48Spatrick
findAvailBackwardCopy(MachineInstr & I,MCRegister Reg,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)23073471bf0Spatrick MachineInstr *findAvailBackwardCopy(MachineInstr &I, MCRegister Reg,
231*d415bd75Srobert const TargetRegisterInfo &TRI,
232*d415bd75Srobert const TargetInstrInfo &TII,
233*d415bd75Srobert bool UseCopyInstr) {
23409467b48Spatrick MCRegUnitIterator RUI(Reg, &TRI);
23509467b48Spatrick MachineInstr *AvailCopy = findCopyDefViaUnit(*RUI, TRI);
236*d415bd75Srobert
237*d415bd75Srobert if (!AvailCopy)
23809467b48Spatrick return nullptr;
23909467b48Spatrick
240*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
241*d415bd75Srobert isCopyInstr(*AvailCopy, TII, UseCopyInstr);
242*d415bd75Srobert Register AvailSrc = CopyOperands->Source->getReg();
243*d415bd75Srobert Register AvailDef = CopyOperands->Destination->getReg();
244*d415bd75Srobert if (!TRI.isSubRegisterEq(AvailSrc, Reg))
245*d415bd75Srobert return nullptr;
246*d415bd75Srobert
24709467b48Spatrick for (const MachineInstr &MI :
24809467b48Spatrick make_range(AvailCopy->getReverseIterator(), I.getReverseIterator()))
24909467b48Spatrick for (const MachineOperand &MO : MI.operands())
25009467b48Spatrick if (MO.isRegMask())
25109467b48Spatrick // FIXME: Shall we simultaneously invalidate AvailSrc or AvailDef?
25209467b48Spatrick if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
25309467b48Spatrick return nullptr;
25409467b48Spatrick
25509467b48Spatrick return AvailCopy;
25609467b48Spatrick }
25709467b48Spatrick
findAvailCopy(MachineInstr & DestCopy,MCRegister Reg,const TargetRegisterInfo & TRI,const TargetInstrInfo & TII,bool UseCopyInstr)25873471bf0Spatrick MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister Reg,
259*d415bd75Srobert const TargetRegisterInfo &TRI,
260*d415bd75Srobert const TargetInstrInfo &TII, bool UseCopyInstr) {
26109467b48Spatrick // We check the first RegUnit here, since we'll only be interested in the
26209467b48Spatrick // copy if it copies the entire register anyway.
26309467b48Spatrick MCRegUnitIterator RUI(Reg, &TRI);
26409467b48Spatrick MachineInstr *AvailCopy =
26509467b48Spatrick findCopyForUnit(*RUI, TRI, /*MustBeAvailable=*/true);
266*d415bd75Srobert
267*d415bd75Srobert if (!AvailCopy)
268*d415bd75Srobert return nullptr;
269*d415bd75Srobert
270*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
271*d415bd75Srobert isCopyInstr(*AvailCopy, TII, UseCopyInstr);
272*d415bd75Srobert Register AvailSrc = CopyOperands->Source->getReg();
273*d415bd75Srobert Register AvailDef = CopyOperands->Destination->getReg();
274*d415bd75Srobert if (!TRI.isSubRegisterEq(AvailDef, Reg))
27509467b48Spatrick return nullptr;
27609467b48Spatrick
27709467b48Spatrick // Check that the available copy isn't clobbered by any regmasks between
27809467b48Spatrick // itself and the destination.
27909467b48Spatrick for (const MachineInstr &MI :
28009467b48Spatrick make_range(AvailCopy->getIterator(), DestCopy.getIterator()))
28109467b48Spatrick for (const MachineOperand &MO : MI.operands())
28209467b48Spatrick if (MO.isRegMask())
28309467b48Spatrick if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
28409467b48Spatrick return nullptr;
28509467b48Spatrick
28609467b48Spatrick return AvailCopy;
28709467b48Spatrick }
28809467b48Spatrick
clear()28909467b48Spatrick void clear() {
29009467b48Spatrick Copies.clear();
29109467b48Spatrick }
29209467b48Spatrick };
29309467b48Spatrick
29409467b48Spatrick class MachineCopyPropagation : public MachineFunctionPass {
29509467b48Spatrick const TargetRegisterInfo *TRI;
29609467b48Spatrick const TargetInstrInfo *TII;
29709467b48Spatrick const MachineRegisterInfo *MRI;
29809467b48Spatrick
299*d415bd75Srobert // Return true if this is a copy instruction and false otherwise.
300*d415bd75Srobert bool UseCopyInstr;
301*d415bd75Srobert
30209467b48Spatrick public:
30309467b48Spatrick static char ID; // Pass identification, replacement for typeid
30409467b48Spatrick
MachineCopyPropagation(bool CopyInstr=false)305*d415bd75Srobert MachineCopyPropagation(bool CopyInstr = false)
306*d415bd75Srobert : MachineFunctionPass(ID), UseCopyInstr(CopyInstr || MCPUseCopyInstr) {
30709467b48Spatrick initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry());
30809467b48Spatrick }
30909467b48Spatrick
getAnalysisUsage(AnalysisUsage & AU) const31009467b48Spatrick void getAnalysisUsage(AnalysisUsage &AU) const override {
31109467b48Spatrick AU.setPreservesCFG();
31209467b48Spatrick MachineFunctionPass::getAnalysisUsage(AU);
31309467b48Spatrick }
31409467b48Spatrick
31509467b48Spatrick bool runOnMachineFunction(MachineFunction &MF) override;
31609467b48Spatrick
getRequiredProperties() const31709467b48Spatrick MachineFunctionProperties getRequiredProperties() const override {
31809467b48Spatrick return MachineFunctionProperties().set(
31909467b48Spatrick MachineFunctionProperties::Property::NoVRegs);
32009467b48Spatrick }
32109467b48Spatrick
32209467b48Spatrick private:
32309467b48Spatrick typedef enum { DebugUse = false, RegularUse = true } DebugType;
32409467b48Spatrick
32573471bf0Spatrick void ReadRegister(MCRegister Reg, MachineInstr &Reader, DebugType DT);
32609467b48Spatrick void ForwardCopyPropagateBlock(MachineBasicBlock &MBB);
32709467b48Spatrick void BackwardCopyPropagateBlock(MachineBasicBlock &MBB);
32873471bf0Spatrick bool eraseIfRedundant(MachineInstr &Copy, MCRegister Src, MCRegister Def);
32909467b48Spatrick void forwardUses(MachineInstr &MI);
33009467b48Spatrick void propagateDefs(MachineInstr &MI);
33109467b48Spatrick bool isForwardableRegClassCopy(const MachineInstr &Copy,
33209467b48Spatrick const MachineInstr &UseI, unsigned UseIdx);
33309467b48Spatrick bool isBackwardPropagatableRegClassCopy(const MachineInstr &Copy,
33409467b48Spatrick const MachineInstr &UseI,
33509467b48Spatrick unsigned UseIdx);
33609467b48Spatrick bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use);
33773471bf0Spatrick bool hasOverlappingMultipleDef(const MachineInstr &MI,
33873471bf0Spatrick const MachineOperand &MODef, Register Def);
33909467b48Spatrick
34009467b48Spatrick /// Candidates for deletion.
34109467b48Spatrick SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
34209467b48Spatrick
34309467b48Spatrick /// Multimap tracking debug users in current BB
34473471bf0Spatrick DenseMap<MachineInstr *, SmallSet<MachineInstr *, 2>> CopyDbgUsers;
34509467b48Spatrick
34609467b48Spatrick CopyTracker Tracker;
34709467b48Spatrick
34809467b48Spatrick bool Changed;
34909467b48Spatrick };
35009467b48Spatrick
35109467b48Spatrick } // end anonymous namespace
35209467b48Spatrick
35309467b48Spatrick char MachineCopyPropagation::ID = 0;
35409467b48Spatrick
35509467b48Spatrick char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;
35609467b48Spatrick
35709467b48Spatrick INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE,
35809467b48Spatrick "Machine Copy Propagation Pass", false, false)
35909467b48Spatrick
ReadRegister(MCRegister Reg,MachineInstr & Reader,DebugType DT)36073471bf0Spatrick void MachineCopyPropagation::ReadRegister(MCRegister Reg, MachineInstr &Reader,
36109467b48Spatrick DebugType DT) {
36209467b48Spatrick // If 'Reg' is defined by a copy, the copy is no longer a candidate
36309467b48Spatrick // for elimination. If a copy is "read" by a debug user, record the user
36409467b48Spatrick // for propagation.
36509467b48Spatrick for (MCRegUnitIterator RUI(Reg, TRI); RUI.isValid(); ++RUI) {
36609467b48Spatrick if (MachineInstr *Copy = Tracker.findCopyForUnit(*RUI, *TRI)) {
36709467b48Spatrick if (DT == RegularUse) {
36809467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump());
36909467b48Spatrick MaybeDeadCopies.remove(Copy);
37009467b48Spatrick } else {
37173471bf0Spatrick CopyDbgUsers[Copy].insert(&Reader);
37209467b48Spatrick }
37309467b48Spatrick }
37409467b48Spatrick }
37509467b48Spatrick }
37609467b48Spatrick
37709467b48Spatrick /// Return true if \p PreviousCopy did copy register \p Src to register \p Def.
37809467b48Spatrick /// This fact may have been obscured by sub register usage or may not be true at
37909467b48Spatrick /// all even though Src and Def are subregisters of the registers used in
38009467b48Spatrick /// PreviousCopy. e.g.
38109467b48Spatrick /// isNopCopy("ecx = COPY eax", AX, CX) == true
38209467b48Spatrick /// isNopCopy("ecx = COPY eax", AH, CL) == false
isNopCopy(const MachineInstr & PreviousCopy,MCRegister Src,MCRegister Def,const TargetRegisterInfo * TRI,const TargetInstrInfo * TII,bool UseCopyInstr)38373471bf0Spatrick static bool isNopCopy(const MachineInstr &PreviousCopy, MCRegister Src,
384*d415bd75Srobert MCRegister Def, const TargetRegisterInfo *TRI,
385*d415bd75Srobert const TargetInstrInfo *TII, bool UseCopyInstr) {
386*d415bd75Srobert
387*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
388*d415bd75Srobert isCopyInstr(PreviousCopy, *TII, UseCopyInstr);
389*d415bd75Srobert MCRegister PreviousSrc = CopyOperands->Source->getReg().asMCReg();
390*d415bd75Srobert MCRegister PreviousDef = CopyOperands->Destination->getReg().asMCReg();
391097a140dSpatrick if (Src == PreviousSrc && Def == PreviousDef)
39209467b48Spatrick return true;
39309467b48Spatrick if (!TRI->isSubRegister(PreviousSrc, Src))
39409467b48Spatrick return false;
39509467b48Spatrick unsigned SubIdx = TRI->getSubRegIndex(PreviousSrc, Src);
39609467b48Spatrick return SubIdx == TRI->getSubRegIndex(PreviousDef, Def);
39709467b48Spatrick }
39809467b48Spatrick
39909467b48Spatrick /// Remove instruction \p Copy if there exists a previous copy that copies the
40009467b48Spatrick /// register \p Src to the register \p Def; This may happen indirectly by
40109467b48Spatrick /// copying the super registers.
eraseIfRedundant(MachineInstr & Copy,MCRegister Src,MCRegister Def)40273471bf0Spatrick bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
40373471bf0Spatrick MCRegister Src, MCRegister Def) {
40409467b48Spatrick // Avoid eliminating a copy from/to a reserved registers as we cannot predict
40509467b48Spatrick // the value (Example: The sparc zero register is writable but stays zero).
40609467b48Spatrick if (MRI->isReserved(Src) || MRI->isReserved(Def))
40709467b48Spatrick return false;
40809467b48Spatrick
40909467b48Spatrick // Search for an existing copy.
410*d415bd75Srobert MachineInstr *PrevCopy =
411*d415bd75Srobert Tracker.findAvailCopy(Copy, Def, *TRI, *TII, UseCopyInstr);
41209467b48Spatrick if (!PrevCopy)
41309467b48Spatrick return false;
41409467b48Spatrick
415*d415bd75Srobert auto PrevCopyOperands = isCopyInstr(*PrevCopy, *TII, UseCopyInstr);
41609467b48Spatrick // Check that the existing copy uses the correct sub registers.
417*d415bd75Srobert if (PrevCopyOperands->Destination->isDead())
41809467b48Spatrick return false;
419*d415bd75Srobert if (!isNopCopy(*PrevCopy, Src, Def, TRI, TII, UseCopyInstr))
42009467b48Spatrick return false;
42109467b48Spatrick
42209467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; Copy.dump());
42309467b48Spatrick
42409467b48Spatrick // Copy was redundantly redefining either Src or Def. Remove earlier kill
42509467b48Spatrick // flags between Copy and PrevCopy because the value will be reused now.
426*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
427*d415bd75Srobert isCopyInstr(Copy, *TII, UseCopyInstr);
428*d415bd75Srobert assert(CopyOperands);
429*d415bd75Srobert
430*d415bd75Srobert Register CopyDef = CopyOperands->Destination->getReg();
43109467b48Spatrick assert(CopyDef == Src || CopyDef == Def);
43209467b48Spatrick for (MachineInstr &MI :
43309467b48Spatrick make_range(PrevCopy->getIterator(), Copy.getIterator()))
43409467b48Spatrick MI.clearRegisterKills(CopyDef, TRI);
43509467b48Spatrick
43609467b48Spatrick Copy.eraseFromParent();
43709467b48Spatrick Changed = true;
43809467b48Spatrick ++NumDeletes;
43909467b48Spatrick return true;
44009467b48Spatrick }
44109467b48Spatrick
isBackwardPropagatableRegClassCopy(const MachineInstr & Copy,const MachineInstr & UseI,unsigned UseIdx)44209467b48Spatrick bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
44309467b48Spatrick const MachineInstr &Copy, const MachineInstr &UseI, unsigned UseIdx) {
444*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
445*d415bd75Srobert isCopyInstr(Copy, *TII, UseCopyInstr);
446*d415bd75Srobert Register Def = CopyOperands->Destination->getReg();
44709467b48Spatrick
44809467b48Spatrick if (const TargetRegisterClass *URC =
44909467b48Spatrick UseI.getRegClassConstraint(UseIdx, TII, TRI))
45009467b48Spatrick return URC->contains(Def);
45109467b48Spatrick
45209467b48Spatrick // We don't process further if UseI is a COPY, since forward copy propagation
45309467b48Spatrick // should handle that.
45409467b48Spatrick return false;
45509467b48Spatrick }
45609467b48Spatrick
45709467b48Spatrick /// Decide whether we should forward the source of \param Copy to its use in
45809467b48Spatrick /// \param UseI based on the physical register class constraints of the opcode
45909467b48Spatrick /// and avoiding introducing more cross-class COPYs.
isForwardableRegClassCopy(const MachineInstr & Copy,const MachineInstr & UseI,unsigned UseIdx)46009467b48Spatrick bool MachineCopyPropagation::isForwardableRegClassCopy(const MachineInstr &Copy,
46109467b48Spatrick const MachineInstr &UseI,
46209467b48Spatrick unsigned UseIdx) {
463*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
464*d415bd75Srobert isCopyInstr(Copy, *TII, UseCopyInstr);
465*d415bd75Srobert Register CopySrcReg = CopyOperands->Source->getReg();
46609467b48Spatrick
46709467b48Spatrick // If the new register meets the opcode register constraints, then allow
46809467b48Spatrick // forwarding.
46909467b48Spatrick if (const TargetRegisterClass *URC =
47009467b48Spatrick UseI.getRegClassConstraint(UseIdx, TII, TRI))
47109467b48Spatrick return URC->contains(CopySrcReg);
47209467b48Spatrick
473*d415bd75Srobert auto UseICopyOperands = isCopyInstr(UseI, *TII, UseCopyInstr);
474*d415bd75Srobert if (!UseICopyOperands)
47509467b48Spatrick return false;
47609467b48Spatrick
47709467b48Spatrick /// COPYs don't have register class constraints, so if the user instruction
47809467b48Spatrick /// is a COPY, we just try to avoid introducing additional cross-class
47909467b48Spatrick /// COPYs. For example:
48009467b48Spatrick ///
48109467b48Spatrick /// RegClassA = COPY RegClassB // Copy parameter
48209467b48Spatrick /// ...
48309467b48Spatrick /// RegClassB = COPY RegClassA // UseI parameter
48409467b48Spatrick ///
48509467b48Spatrick /// which after forwarding becomes
48609467b48Spatrick ///
48709467b48Spatrick /// RegClassA = COPY RegClassB
48809467b48Spatrick /// ...
48909467b48Spatrick /// RegClassB = COPY RegClassB
49009467b48Spatrick ///
49109467b48Spatrick /// so we have reduced the number of cross-class COPYs and potentially
49209467b48Spatrick /// introduced a nop COPY that can be removed.
49309467b48Spatrick
494*d415bd75Srobert // Allow forwarding if src and dst belong to any common class, so long as they
495*d415bd75Srobert // don't belong to any (possibly smaller) common class that requires copies to
496*d415bd75Srobert // go via a different class.
497*d415bd75Srobert Register UseDstReg = UseICopyOperands->Destination->getReg();
498*d415bd75Srobert bool Found = false;
499*d415bd75Srobert bool IsCrossClass = false;
500*d415bd75Srobert for (const TargetRegisterClass *RC : TRI->regclasses()) {
501*d415bd75Srobert if (RC->contains(CopySrcReg) && RC->contains(UseDstReg)) {
502*d415bd75Srobert Found = true;
503*d415bd75Srobert if (TRI->getCrossCopyRegClass(RC) != RC) {
504*d415bd75Srobert IsCrossClass = true;
505*d415bd75Srobert break;
506*d415bd75Srobert }
507*d415bd75Srobert }
508*d415bd75Srobert }
509*d415bd75Srobert if (!Found)
510*d415bd75Srobert return false;
511*d415bd75Srobert if (!IsCrossClass)
51209467b48Spatrick return true;
513*d415bd75Srobert // The forwarded copy would be cross-class. Only do this if the original copy
514*d415bd75Srobert // was also cross-class.
515*d415bd75Srobert Register CopyDstReg = CopyOperands->Destination->getReg();
516*d415bd75Srobert for (const TargetRegisterClass *RC : TRI->regclasses()) {
517*d415bd75Srobert if (RC->contains(CopySrcReg) && RC->contains(CopyDstReg) &&
518*d415bd75Srobert TRI->getCrossCopyRegClass(RC) != RC)
519*d415bd75Srobert return true;
520*d415bd75Srobert }
52109467b48Spatrick return false;
52209467b48Spatrick }
52309467b48Spatrick
52409467b48Spatrick /// Check that \p MI does not have implicit uses that overlap with it's \p Use
52509467b48Spatrick /// operand (the register being replaced), since these can sometimes be
52609467b48Spatrick /// implicitly tied to other operands. For example, on AMDGPU:
52709467b48Spatrick ///
52809467b48Spatrick /// V_MOVRELS_B32_e32 %VGPR2, %M0<imp-use>, %EXEC<imp-use>, %VGPR2_VGPR3_VGPR4_VGPR5<imp-use>
52909467b48Spatrick ///
53009467b48Spatrick /// the %VGPR2 is implicitly tied to the larger reg operand, but we have no
53109467b48Spatrick /// way of knowing we need to update the latter when updating the former.
hasImplicitOverlap(const MachineInstr & MI,const MachineOperand & Use)53209467b48Spatrick bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI,
53309467b48Spatrick const MachineOperand &Use) {
53409467b48Spatrick for (const MachineOperand &MIUse : MI.uses())
53509467b48Spatrick if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
53609467b48Spatrick MIUse.isUse() && TRI->regsOverlap(Use.getReg(), MIUse.getReg()))
53709467b48Spatrick return true;
53809467b48Spatrick
53909467b48Spatrick return false;
54009467b48Spatrick }
54109467b48Spatrick
54273471bf0Spatrick /// For an MI that has multiple definitions, check whether \p MI has
54373471bf0Spatrick /// a definition that overlaps with another of its definitions.
54473471bf0Spatrick /// For example, on ARM: umull r9, r9, lr, r0
54573471bf0Spatrick /// The umull instruction is unpredictable unless RdHi and RdLo are different.
hasOverlappingMultipleDef(const MachineInstr & MI,const MachineOperand & MODef,Register Def)54673471bf0Spatrick bool MachineCopyPropagation::hasOverlappingMultipleDef(
54773471bf0Spatrick const MachineInstr &MI, const MachineOperand &MODef, Register Def) {
54873471bf0Spatrick for (const MachineOperand &MIDef : MI.defs()) {
54973471bf0Spatrick if ((&MIDef != &MODef) && MIDef.isReg() &&
55073471bf0Spatrick TRI->regsOverlap(Def, MIDef.getReg()))
55173471bf0Spatrick return true;
55273471bf0Spatrick }
55373471bf0Spatrick
55473471bf0Spatrick return false;
55573471bf0Spatrick }
55673471bf0Spatrick
55709467b48Spatrick /// Look for available copies whose destination register is used by \p MI and
55809467b48Spatrick /// replace the use in \p MI with the copy's source register.
forwardUses(MachineInstr & MI)55909467b48Spatrick void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
56009467b48Spatrick if (!Tracker.hasAnyCopies())
56109467b48Spatrick return;
56209467b48Spatrick
56309467b48Spatrick // Look for non-tied explicit vreg uses that have an active COPY
56409467b48Spatrick // instruction that defines the physical register allocated to them.
56509467b48Spatrick // Replace the vreg with the source of the active COPY.
56609467b48Spatrick for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx < OpEnd;
56709467b48Spatrick ++OpIdx) {
56809467b48Spatrick MachineOperand &MOUse = MI.getOperand(OpIdx);
56909467b48Spatrick // Don't forward into undef use operands since doing so can cause problems
57009467b48Spatrick // with the machine verifier, since it doesn't treat undef reads as reads,
57109467b48Spatrick // so we can end up with a live range that ends on an undef read, leading to
57209467b48Spatrick // an error that the live range doesn't end on a read of the live range
57309467b48Spatrick // register.
57409467b48Spatrick if (!MOUse.isReg() || MOUse.isTied() || MOUse.isUndef() || MOUse.isDef() ||
57509467b48Spatrick MOUse.isImplicit())
57609467b48Spatrick continue;
57709467b48Spatrick
57809467b48Spatrick if (!MOUse.getReg())
57909467b48Spatrick continue;
58009467b48Spatrick
58109467b48Spatrick // Check that the register is marked 'renamable' so we know it is safe to
58209467b48Spatrick // rename it without violating any constraints that aren't expressed in the
58309467b48Spatrick // IR (e.g. ABI or opcode requirements).
58409467b48Spatrick if (!MOUse.isRenamable())
58509467b48Spatrick continue;
58609467b48Spatrick
587*d415bd75Srobert MachineInstr *Copy = Tracker.findAvailCopy(MI, MOUse.getReg().asMCReg(),
588*d415bd75Srobert *TRI, *TII, UseCopyInstr);
58909467b48Spatrick if (!Copy)
59009467b48Spatrick continue;
59109467b48Spatrick
592*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
593*d415bd75Srobert isCopyInstr(*Copy, *TII, UseCopyInstr);
594*d415bd75Srobert Register CopyDstReg = CopyOperands->Destination->getReg();
595*d415bd75Srobert const MachineOperand &CopySrc = *CopyOperands->Source;
59609467b48Spatrick Register CopySrcReg = CopySrc.getReg();
59709467b48Spatrick
59809467b48Spatrick // FIXME: Don't handle partial uses of wider COPYs yet.
59909467b48Spatrick if (MOUse.getReg() != CopyDstReg) {
60009467b48Spatrick LLVM_DEBUG(
60109467b48Spatrick dbgs() << "MCP: FIXME! Not forwarding COPY to sub-register use:\n "
60209467b48Spatrick << MI);
60309467b48Spatrick continue;
60409467b48Spatrick }
60509467b48Spatrick
60609467b48Spatrick // Don't forward COPYs of reserved regs unless they are constant.
60709467b48Spatrick if (MRI->isReserved(CopySrcReg) && !MRI->isConstantPhysReg(CopySrcReg))
60809467b48Spatrick continue;
60909467b48Spatrick
61009467b48Spatrick if (!isForwardableRegClassCopy(*Copy, MI, OpIdx))
61109467b48Spatrick continue;
61209467b48Spatrick
61309467b48Spatrick if (hasImplicitOverlap(MI, MOUse))
61409467b48Spatrick continue;
61509467b48Spatrick
61609467b48Spatrick // Check that the instruction is not a copy that partially overwrites the
61709467b48Spatrick // original copy source that we are about to use. The tracker mechanism
61809467b48Spatrick // cannot cope with that.
619*d415bd75Srobert if (isCopyInstr(MI, *TII, UseCopyInstr) &&
620*d415bd75Srobert MI.modifiesRegister(CopySrcReg, TRI) &&
62109467b48Spatrick !MI.definesRegister(CopySrcReg)) {
62209467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: Copy source overlap with dest in " << MI);
62309467b48Spatrick continue;
62409467b48Spatrick }
62509467b48Spatrick
62609467b48Spatrick if (!DebugCounter::shouldExecute(FwdCounter)) {
62709467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: Skipping forwarding due to debug counter:\n "
62809467b48Spatrick << MI);
62909467b48Spatrick continue;
63009467b48Spatrick }
63109467b48Spatrick
63209467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MOUse.getReg(), TRI)
63309467b48Spatrick << "\n with " << printReg(CopySrcReg, TRI)
63409467b48Spatrick << "\n in " << MI << " from " << *Copy);
63509467b48Spatrick
63609467b48Spatrick MOUse.setReg(CopySrcReg);
63709467b48Spatrick if (!CopySrc.isRenamable())
63809467b48Spatrick MOUse.setIsRenamable(false);
639*d415bd75Srobert MOUse.setIsUndef(CopySrc.isUndef());
64009467b48Spatrick
64109467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
64209467b48Spatrick
64309467b48Spatrick // Clear kill markers that may have been invalidated.
64409467b48Spatrick for (MachineInstr &KMI :
64509467b48Spatrick make_range(Copy->getIterator(), std::next(MI.getIterator())))
64609467b48Spatrick KMI.clearRegisterKills(CopySrcReg, TRI);
64709467b48Spatrick
64809467b48Spatrick ++NumCopyForwards;
64909467b48Spatrick Changed = true;
65009467b48Spatrick }
65109467b48Spatrick }
65209467b48Spatrick
ForwardCopyPropagateBlock(MachineBasicBlock & MBB)65309467b48Spatrick void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {
65409467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: ForwardCopyPropagateBlock " << MBB.getName()
65509467b48Spatrick << "\n");
65609467b48Spatrick
657*d415bd75Srobert for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
65809467b48Spatrick // Analyze copies (which don't overlap themselves).
659*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
660*d415bd75Srobert isCopyInstr(MI, *TII, UseCopyInstr);
661*d415bd75Srobert if (CopyOperands) {
662*d415bd75Srobert
663*d415bd75Srobert Register RegSrc = CopyOperands->Source->getReg();
664*d415bd75Srobert Register RegDef = CopyOperands->Destination->getReg();
665*d415bd75Srobert
666*d415bd75Srobert if (!TRI->regsOverlap(RegDef, RegSrc)) {
667*d415bd75Srobert assert(RegDef.isPhysical() && RegSrc.isPhysical() &&
66809467b48Spatrick "MachineCopyPropagation should be run after register allocation!");
66909467b48Spatrick
670*d415bd75Srobert MCRegister Def = RegDef.asMCReg();
671*d415bd75Srobert MCRegister Src = RegSrc.asMCReg();
67273471bf0Spatrick
67309467b48Spatrick // The two copies cancel out and the source of the first copy
67409467b48Spatrick // hasn't been overridden, eliminate the second one. e.g.
67509467b48Spatrick // %ecx = COPY %eax
67609467b48Spatrick // ... nothing clobbered eax.
67709467b48Spatrick // %eax = COPY %ecx
67809467b48Spatrick // =>
67909467b48Spatrick // %ecx = COPY %eax
68009467b48Spatrick //
68109467b48Spatrick // or
68209467b48Spatrick //
68309467b48Spatrick // %ecx = COPY %eax
68409467b48Spatrick // ... nothing clobbered eax.
68509467b48Spatrick // %ecx = COPY %eax
68609467b48Spatrick // =>
68709467b48Spatrick // %ecx = COPY %eax
688*d415bd75Srobert if (eraseIfRedundant(MI, Def, Src) || eraseIfRedundant(MI, Src, Def))
68909467b48Spatrick continue;
69009467b48Spatrick
691*d415bd75Srobert forwardUses(MI);
69209467b48Spatrick
69309467b48Spatrick // Src may have been changed by forwardUses()
694*d415bd75Srobert CopyOperands = isCopyInstr(MI, *TII, UseCopyInstr);
695*d415bd75Srobert Src = CopyOperands->Source->getReg().asMCReg();
69609467b48Spatrick
69709467b48Spatrick // If Src is defined by a previous copy, the previous copy cannot be
69809467b48Spatrick // eliminated.
699*d415bd75Srobert ReadRegister(Src, MI, RegularUse);
700*d415bd75Srobert for (const MachineOperand &MO : MI.implicit_operands()) {
70109467b48Spatrick if (!MO.isReg() || !MO.readsReg())
70209467b48Spatrick continue;
70373471bf0Spatrick MCRegister Reg = MO.getReg().asMCReg();
70409467b48Spatrick if (!Reg)
70509467b48Spatrick continue;
706*d415bd75Srobert ReadRegister(Reg, MI, RegularUse);
70709467b48Spatrick }
70809467b48Spatrick
709*d415bd75Srobert LLVM_DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI.dump());
71009467b48Spatrick
71109467b48Spatrick // Copy is now a candidate for deletion.
71209467b48Spatrick if (!MRI->isReserved(Def))
713*d415bd75Srobert MaybeDeadCopies.insert(&MI);
71409467b48Spatrick
71509467b48Spatrick // If 'Def' is previously source of another copy, then this earlier copy's
71609467b48Spatrick // source is no longer available. e.g.
71709467b48Spatrick // %xmm9 = copy %xmm2
71809467b48Spatrick // ...
71909467b48Spatrick // %xmm2 = copy %xmm0
72009467b48Spatrick // ...
72109467b48Spatrick // %xmm2 = copy %xmm9
722*d415bd75Srobert Tracker.clobberRegister(Def, *TRI, *TII, UseCopyInstr);
723*d415bd75Srobert for (const MachineOperand &MO : MI.implicit_operands()) {
72409467b48Spatrick if (!MO.isReg() || !MO.isDef())
72509467b48Spatrick continue;
72673471bf0Spatrick MCRegister Reg = MO.getReg().asMCReg();
72709467b48Spatrick if (!Reg)
72809467b48Spatrick continue;
729*d415bd75Srobert Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
73009467b48Spatrick }
73109467b48Spatrick
732*d415bd75Srobert Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
73309467b48Spatrick
73409467b48Spatrick continue;
73509467b48Spatrick }
736*d415bd75Srobert }
73709467b48Spatrick
73809467b48Spatrick // Clobber any earlyclobber regs first.
739*d415bd75Srobert for (const MachineOperand &MO : MI.operands())
74009467b48Spatrick if (MO.isReg() && MO.isEarlyClobber()) {
74173471bf0Spatrick MCRegister Reg = MO.getReg().asMCReg();
74209467b48Spatrick // If we have a tied earlyclobber, that means it is also read by this
74309467b48Spatrick // instruction, so we need to make sure we don't remove it as dead
74409467b48Spatrick // later.
74509467b48Spatrick if (MO.isTied())
746*d415bd75Srobert ReadRegister(Reg, MI, RegularUse);
747*d415bd75Srobert Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
74809467b48Spatrick }
74909467b48Spatrick
750*d415bd75Srobert forwardUses(MI);
75109467b48Spatrick
75209467b48Spatrick // Not a copy.
75373471bf0Spatrick SmallVector<Register, 2> Defs;
75409467b48Spatrick const MachineOperand *RegMask = nullptr;
755*d415bd75Srobert for (const MachineOperand &MO : MI.operands()) {
75609467b48Spatrick if (MO.isRegMask())
75709467b48Spatrick RegMask = &MO;
75809467b48Spatrick if (!MO.isReg())
75909467b48Spatrick continue;
76009467b48Spatrick Register Reg = MO.getReg();
76109467b48Spatrick if (!Reg)
76209467b48Spatrick continue;
76309467b48Spatrick
76473471bf0Spatrick assert(!Reg.isVirtual() &&
76509467b48Spatrick "MachineCopyPropagation should be run after register allocation!");
76609467b48Spatrick
76709467b48Spatrick if (MO.isDef() && !MO.isEarlyClobber()) {
76873471bf0Spatrick Defs.push_back(Reg.asMCReg());
76909467b48Spatrick continue;
77009467b48Spatrick } else if (MO.readsReg())
771*d415bd75Srobert ReadRegister(Reg.asMCReg(), MI, MO.isDebug() ? DebugUse : RegularUse);
77209467b48Spatrick }
77309467b48Spatrick
77409467b48Spatrick // The instruction has a register mask operand which means that it clobbers
77509467b48Spatrick // a large set of registers. Treat clobbered registers the same way as
77609467b48Spatrick // defined registers.
77709467b48Spatrick if (RegMask) {
77809467b48Spatrick // Erase any MaybeDeadCopies whose destination register is clobbered.
77909467b48Spatrick for (SmallSetVector<MachineInstr *, 8>::iterator DI =
78009467b48Spatrick MaybeDeadCopies.begin();
78109467b48Spatrick DI != MaybeDeadCopies.end();) {
78209467b48Spatrick MachineInstr *MaybeDead = *DI;
783*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
784*d415bd75Srobert isCopyInstr(*MaybeDead, *TII, UseCopyInstr);
785*d415bd75Srobert MCRegister Reg = CopyOperands->Destination->getReg().asMCReg();
78609467b48Spatrick assert(!MRI->isReserved(Reg));
78709467b48Spatrick
78809467b48Spatrick if (!RegMask->clobbersPhysReg(Reg)) {
78909467b48Spatrick ++DI;
79009467b48Spatrick continue;
79109467b48Spatrick }
79209467b48Spatrick
79309467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: ";
79409467b48Spatrick MaybeDead->dump());
79509467b48Spatrick
79609467b48Spatrick // Make sure we invalidate any entries in the copy maps before erasing
79709467b48Spatrick // the instruction.
798*d415bd75Srobert Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
79909467b48Spatrick
80009467b48Spatrick // erase() will return the next valid iterator pointing to the next
80109467b48Spatrick // element after the erased one.
80209467b48Spatrick DI = MaybeDeadCopies.erase(DI);
80309467b48Spatrick MaybeDead->eraseFromParent();
80409467b48Spatrick Changed = true;
80509467b48Spatrick ++NumDeletes;
80609467b48Spatrick }
80709467b48Spatrick }
80809467b48Spatrick
80909467b48Spatrick // Any previous copy definition or reading the Defs is no longer available.
81073471bf0Spatrick for (MCRegister Reg : Defs)
811*d415bd75Srobert Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
81209467b48Spatrick }
81309467b48Spatrick
81409467b48Spatrick // If MBB doesn't have successors, delete the copies whose defs are not used.
81509467b48Spatrick // If MBB does have successors, then conservative assume the defs are live-out
81609467b48Spatrick // since we don't want to trust live-in lists.
81709467b48Spatrick if (MBB.succ_empty()) {
81809467b48Spatrick for (MachineInstr *MaybeDead : MaybeDeadCopies) {
81909467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: ";
82009467b48Spatrick MaybeDead->dump());
821*d415bd75Srobert
822*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
823*d415bd75Srobert isCopyInstr(*MaybeDead, *TII, UseCopyInstr);
824*d415bd75Srobert assert(CopyOperands);
825*d415bd75Srobert
826*d415bd75Srobert Register SrcReg = CopyOperands->Source->getReg();
827*d415bd75Srobert Register DestReg = CopyOperands->Destination->getReg();
828*d415bd75Srobert assert(!MRI->isReserved(DestReg));
82909467b48Spatrick
83009467b48Spatrick // Update matching debug values, if any.
83173471bf0Spatrick SmallVector<MachineInstr *> MaybeDeadDbgUsers(
83273471bf0Spatrick CopyDbgUsers[MaybeDead].begin(), CopyDbgUsers[MaybeDead].end());
83373471bf0Spatrick MRI->updateDbgUsersToReg(DestReg.asMCReg(), SrcReg.asMCReg(),
83473471bf0Spatrick MaybeDeadDbgUsers);
83509467b48Spatrick
83609467b48Spatrick MaybeDead->eraseFromParent();
83709467b48Spatrick Changed = true;
83809467b48Spatrick ++NumDeletes;
83909467b48Spatrick }
84009467b48Spatrick }
84109467b48Spatrick
84209467b48Spatrick MaybeDeadCopies.clear();
84309467b48Spatrick CopyDbgUsers.clear();
84409467b48Spatrick Tracker.clear();
84509467b48Spatrick }
84609467b48Spatrick
isBackwardPropagatableCopy(MachineInstr & MI,const MachineRegisterInfo & MRI,const TargetInstrInfo & TII,bool UseCopyInstr)84709467b48Spatrick static bool isBackwardPropagatableCopy(MachineInstr &MI,
848*d415bd75Srobert const MachineRegisterInfo &MRI,
849*d415bd75Srobert const TargetInstrInfo &TII,
850*d415bd75Srobert bool UseCopyInstr) {
851*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
852*d415bd75Srobert isCopyInstr(MI, TII, UseCopyInstr);
853*d415bd75Srobert assert(CopyOperands && "MI is expected to be a COPY");
854*d415bd75Srobert
855*d415bd75Srobert Register Def = CopyOperands->Destination->getReg();
856*d415bd75Srobert Register Src = CopyOperands->Source->getReg();
85709467b48Spatrick
85809467b48Spatrick if (!Def || !Src)
85909467b48Spatrick return false;
86009467b48Spatrick
86109467b48Spatrick if (MRI.isReserved(Def) || MRI.isReserved(Src))
86209467b48Spatrick return false;
86309467b48Spatrick
864*d415bd75Srobert return CopyOperands->Source->isRenamable() && CopyOperands->Source->isKill();
86509467b48Spatrick }
86609467b48Spatrick
propagateDefs(MachineInstr & MI)86709467b48Spatrick void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
86809467b48Spatrick if (!Tracker.hasAnyCopies())
86909467b48Spatrick return;
87009467b48Spatrick
87109467b48Spatrick for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx != OpEnd;
87209467b48Spatrick ++OpIdx) {
87309467b48Spatrick MachineOperand &MODef = MI.getOperand(OpIdx);
87409467b48Spatrick
87509467b48Spatrick if (!MODef.isReg() || MODef.isUse())
87609467b48Spatrick continue;
87709467b48Spatrick
87809467b48Spatrick // Ignore non-trivial cases.
87909467b48Spatrick if (MODef.isTied() || MODef.isUndef() || MODef.isImplicit())
88009467b48Spatrick continue;
88109467b48Spatrick
88209467b48Spatrick if (!MODef.getReg())
88309467b48Spatrick continue;
88409467b48Spatrick
88509467b48Spatrick // We only handle if the register comes from a vreg.
88609467b48Spatrick if (!MODef.isRenamable())
88709467b48Spatrick continue;
88809467b48Spatrick
889*d415bd75Srobert MachineInstr *Copy = Tracker.findAvailBackwardCopy(
890*d415bd75Srobert MI, MODef.getReg().asMCReg(), *TRI, *TII, UseCopyInstr);
89109467b48Spatrick if (!Copy)
89209467b48Spatrick continue;
89309467b48Spatrick
894*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
895*d415bd75Srobert isCopyInstr(*Copy, *TII, UseCopyInstr);
896*d415bd75Srobert Register Def = CopyOperands->Destination->getReg();
897*d415bd75Srobert Register Src = CopyOperands->Source->getReg();
89809467b48Spatrick
89909467b48Spatrick if (MODef.getReg() != Src)
90009467b48Spatrick continue;
90109467b48Spatrick
90209467b48Spatrick if (!isBackwardPropagatableRegClassCopy(*Copy, MI, OpIdx))
90309467b48Spatrick continue;
90409467b48Spatrick
90509467b48Spatrick if (hasImplicitOverlap(MI, MODef))
90609467b48Spatrick continue;
90709467b48Spatrick
90873471bf0Spatrick if (hasOverlappingMultipleDef(MI, MODef, Def))
90973471bf0Spatrick continue;
91073471bf0Spatrick
91109467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MODef.getReg(), TRI)
91209467b48Spatrick << "\n with " << printReg(Def, TRI) << "\n in "
91309467b48Spatrick << MI << " from " << *Copy);
91409467b48Spatrick
91509467b48Spatrick MODef.setReg(Def);
916*d415bd75Srobert MODef.setIsRenamable(CopyOperands->Destination->isRenamable());
91709467b48Spatrick
91809467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
91909467b48Spatrick MaybeDeadCopies.insert(Copy);
92009467b48Spatrick Changed = true;
92109467b48Spatrick ++NumCopyBackwardPropagated;
92209467b48Spatrick }
92309467b48Spatrick }
92409467b48Spatrick
BackwardCopyPropagateBlock(MachineBasicBlock & MBB)92509467b48Spatrick void MachineCopyPropagation::BackwardCopyPropagateBlock(
92609467b48Spatrick MachineBasicBlock &MBB) {
92709467b48Spatrick LLVM_DEBUG(dbgs() << "MCP: BackwardCopyPropagateBlock " << MBB.getName()
92809467b48Spatrick << "\n");
92909467b48Spatrick
930*d415bd75Srobert for (MachineInstr &MI : llvm::make_early_inc_range(llvm::reverse(MBB))) {
93109467b48Spatrick // Ignore non-trivial COPYs.
932*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
933*d415bd75Srobert isCopyInstr(MI, *TII, UseCopyInstr);
934*d415bd75Srobert if (CopyOperands && MI.getNumOperands() == 2) {
935*d415bd75Srobert Register DefReg = CopyOperands->Destination->getReg();
936*d415bd75Srobert Register SrcReg = CopyOperands->Source->getReg();
93709467b48Spatrick
938*d415bd75Srobert if (!TRI->regsOverlap(DefReg, SrcReg)) {
939*d415bd75Srobert MCRegister Def = DefReg.asMCReg();
940*d415bd75Srobert MCRegister Src = SrcReg.asMCReg();
94109467b48Spatrick
94209467b48Spatrick // Unlike forward cp, we don't invoke propagateDefs here,
94309467b48Spatrick // just let forward cp do COPY-to-COPY propagation.
944*d415bd75Srobert if (isBackwardPropagatableCopy(MI, *MRI, *TII, UseCopyInstr)) {
945*d415bd75Srobert Tracker.invalidateRegister(Src, *TRI, *TII, UseCopyInstr);
946*d415bd75Srobert Tracker.invalidateRegister(Def, *TRI, *TII, UseCopyInstr);
947*d415bd75Srobert Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
94809467b48Spatrick continue;
94909467b48Spatrick }
95009467b48Spatrick }
951*d415bd75Srobert }
95209467b48Spatrick
95309467b48Spatrick // Invalidate any earlyclobber regs first.
954*d415bd75Srobert for (const MachineOperand &MO : MI.operands())
95509467b48Spatrick if (MO.isReg() && MO.isEarlyClobber()) {
95673471bf0Spatrick MCRegister Reg = MO.getReg().asMCReg();
95709467b48Spatrick if (!Reg)
95809467b48Spatrick continue;
959*d415bd75Srobert Tracker.invalidateRegister(Reg, *TRI, *TII, UseCopyInstr);
96009467b48Spatrick }
96109467b48Spatrick
962*d415bd75Srobert propagateDefs(MI);
963*d415bd75Srobert for (const MachineOperand &MO : MI.operands()) {
96409467b48Spatrick if (!MO.isReg())
96509467b48Spatrick continue;
96609467b48Spatrick
96709467b48Spatrick if (!MO.getReg())
96809467b48Spatrick continue;
96909467b48Spatrick
97009467b48Spatrick if (MO.isDef())
971*d415bd75Srobert Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
972*d415bd75Srobert UseCopyInstr);
97309467b48Spatrick
97473471bf0Spatrick if (MO.readsReg()) {
97573471bf0Spatrick if (MO.isDebug()) {
97673471bf0Spatrick // Check if the register in the debug instruction is utilized
97773471bf0Spatrick // in a copy instruction, so we can update the debug info if the
97873471bf0Spatrick // register is changed.
97973471bf0Spatrick for (MCRegUnitIterator RUI(MO.getReg().asMCReg(), TRI); RUI.isValid();
98073471bf0Spatrick ++RUI) {
98173471bf0Spatrick if (auto *Copy = Tracker.findCopyDefViaUnit(*RUI, *TRI)) {
982*d415bd75Srobert CopyDbgUsers[Copy].insert(&MI);
98373471bf0Spatrick }
98473471bf0Spatrick }
98573471bf0Spatrick } else {
986*d415bd75Srobert Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
987*d415bd75Srobert UseCopyInstr);
98873471bf0Spatrick }
98973471bf0Spatrick }
99009467b48Spatrick }
99109467b48Spatrick }
99209467b48Spatrick
99309467b48Spatrick for (auto *Copy : MaybeDeadCopies) {
994*d415bd75Srobert std::optional<DestSourcePair> CopyOperands =
995*d415bd75Srobert isCopyInstr(*Copy, *TII, UseCopyInstr);
996*d415bd75Srobert Register Src = CopyOperands->Source->getReg();
997*d415bd75Srobert Register Def = CopyOperands->Destination->getReg();
99873471bf0Spatrick SmallVector<MachineInstr *> MaybeDeadDbgUsers(CopyDbgUsers[Copy].begin(),
99973471bf0Spatrick CopyDbgUsers[Copy].end());
100073471bf0Spatrick
100173471bf0Spatrick MRI->updateDbgUsersToReg(Src.asMCReg(), Def.asMCReg(), MaybeDeadDbgUsers);
100209467b48Spatrick Copy->eraseFromParent();
100309467b48Spatrick ++NumDeletes;
100409467b48Spatrick }
100509467b48Spatrick
100609467b48Spatrick MaybeDeadCopies.clear();
100709467b48Spatrick CopyDbgUsers.clear();
100809467b48Spatrick Tracker.clear();
100909467b48Spatrick }
101009467b48Spatrick
runOnMachineFunction(MachineFunction & MF)101109467b48Spatrick bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
101209467b48Spatrick if (skipFunction(MF.getFunction()))
101309467b48Spatrick return false;
101409467b48Spatrick
101509467b48Spatrick Changed = false;
101609467b48Spatrick
101709467b48Spatrick TRI = MF.getSubtarget().getRegisterInfo();
101809467b48Spatrick TII = MF.getSubtarget().getInstrInfo();
101909467b48Spatrick MRI = &MF.getRegInfo();
102009467b48Spatrick
102109467b48Spatrick for (MachineBasicBlock &MBB : MF) {
102209467b48Spatrick BackwardCopyPropagateBlock(MBB);
102309467b48Spatrick ForwardCopyPropagateBlock(MBB);
102409467b48Spatrick }
102509467b48Spatrick
102609467b48Spatrick return Changed;
102709467b48Spatrick }
1028*d415bd75Srobert
1029*d415bd75Srobert MachineFunctionPass *
createMachineCopyPropagationPass(bool UseCopyInstr=false)1030*d415bd75Srobert llvm::createMachineCopyPropagationPass(bool UseCopyInstr = false) {
1031*d415bd75Srobert return new MachineCopyPropagation(UseCopyInstr);
1032*d415bd75Srobert }
1033