1 //===- RDFCopy.cpp --------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // RDF-based copy propagation.
11 //===----------------------------------------------------------------------===//
14 #include "llvm/CodeGen/MachineDominators.h"
15 #include "llvm/CodeGen/MachineInstr.h"
16 #include "llvm/CodeGen/MachineOperand.h"
17 #include "llvm/CodeGen/RDFGraph.h"
18 #include "llvm/CodeGen/RDFLiveness.h"
19 #include "llvm/CodeGen/RDFRegisters.h"
20 #include "llvm/CodeGen/TargetOpcodes.h"
21 #include "llvm/CodeGen/TargetRegisterInfo.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/Support/CommandLine.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/raw_ostream.h"
35 static cl::opt
<unsigned> CpLimit("rdf-cp-limit", cl::init(0), cl::Hidden
);
36 static unsigned CpCount
= 0;
39 bool CopyPropagation::interpretAsCopy(const MachineInstr
*MI
, EqualityMap
&EM
) {
40 unsigned Opc
= MI
->getOpcode();
42 case TargetOpcode::COPY
: {
43 const MachineOperand
&Dst
= MI
->getOperand(0);
44 const MachineOperand
&Src
= MI
->getOperand(1);
45 RegisterRef DstR
= DFG
.makeRegRef(Dst
.getReg(), Dst
.getSubReg());
46 RegisterRef SrcR
= DFG
.makeRegRef(Src
.getReg(), Src
.getSubReg());
47 assert(Register::isPhysicalRegister(DstR
.Reg
));
48 assert(Register::isPhysicalRegister(SrcR
.Reg
));
49 const TargetRegisterInfo
&TRI
= DFG
.getTRI();
50 if (TRI
.getMinimalPhysRegClass(DstR
.Reg
) !=
51 TRI
.getMinimalPhysRegClass(SrcR
.Reg
))
53 if (!DFG
.isTracked(SrcR
) || !DFG
.isTracked(DstR
))
55 EM
.insert(std::make_pair(DstR
, SrcR
));
58 case TargetOpcode::REG_SEQUENCE
:
59 llvm_unreachable("Unexpected REG_SEQUENCE");
64 void CopyPropagation::recordCopy(NodeAddr
<StmtNode
*> SA
, EqualityMap
&EM
) {
65 CopyMap
.insert(std::make_pair(SA
.Id
, EM
));
66 Copies
.push_back(SA
.Id
);
69 auto FS
= DefM
.find(I
.second
.Reg
);
70 if (FS
== DefM
.end() || FS
->second
.empty())
71 continue; // Undefined source
72 RDefMap
[I
.second
][SA
.Id
] = FS
->second
.top()->Id
;
73 // Insert DstR into the map.
79 void CopyPropagation::updateMap(NodeAddr
<InstrNode
*> IA
) {
80 RegisterSet
RRs(DFG
.getPRI());
81 for (NodeAddr
<RefNode
*> RA
: IA
.Addr
->members(DFG
))
82 RRs
.insert(RA
.Addr
->getRegRef(DFG
));
84 for (auto &R
: RDefMap
) {
85 if (!RRs
.count(R
.first
))
93 for (auto &R
: RDefMap
) {
94 if (!RRs
.count(R
.first
))
96 auto F
= DefM
.find(R
.first
.Reg
);
97 if (F
== DefM
.end() || F
->second
.empty())
99 R
.second
[IA
.Id
] = F
->second
.top()->Id
;
103 bool CopyPropagation::scanBlock(MachineBasicBlock
*B
) {
104 bool Changed
= false;
105 NodeAddr
<BlockNode
*> BA
= DFG
.findBlock(B
);
106 DFG
.markBlock(BA
.Id
, DefM
);
108 for (NodeAddr
<InstrNode
*> IA
: BA
.Addr
->members(DFG
)) {
109 if (DFG
.IsCode
<NodeAttrs::Stmt
>(IA
)) {
110 NodeAddr
<StmtNode
*> SA
= IA
;
111 EqualityMap
EM(std::less
<RegisterRef
>(DFG
.getPRI()));
112 if (interpretAsCopy(SA
.Addr
->getCode(), EM
))
117 DFG
.pushAllDefs(IA
, DefM
);
120 MachineDomTreeNode
*N
= MDT
.getNode(B
);
122 Changed
|= scanBlock(I
->getBlock());
124 DFG
.releaseBlock(BA
.Id
, DefM
);
128 bool CopyPropagation::run() {
129 scanBlock(&DFG
.getMF().front());
132 dbgs() << "Copies:\n";
133 for (NodeId I
: Copies
) {
134 dbgs() << "Instr: " << *DFG
.addr
<StmtNode
*>(I
).Addr
->getCode();
136 if (CopyMap
.count(I
)) {
137 for (auto J
: CopyMap
.at(I
))
138 dbgs() << ' ' << Print
<RegisterRef
>(J
.first
, DFG
) << '='
139 << Print
<RegisterRef
>(J
.second
, DFG
);
143 dbgs() << "\nRDef map:\n";
144 for (auto R
: RDefMap
) {
145 dbgs() << Print
<RegisterRef
>(R
.first
, DFG
) << " -> {";
146 for (auto &M
: R
.second
)
147 dbgs() << ' ' << Print
<NodeId
>(M
.first
, DFG
) << ':'
148 << Print
<NodeId
>(M
.second
, DFG
);
153 bool Changed
= false;
155 bool HasLimit
= CpLimit
.getNumOccurrences() > 0;
158 auto MinPhysReg
= [this] (RegisterRef RR
) -> unsigned {
159 const TargetRegisterInfo
&TRI
= DFG
.getTRI();
160 const TargetRegisterClass
&RC
= *TRI
.getMinimalPhysRegClass(RR
.Reg
);
161 if ((RC
.LaneMask
& RR
.Mask
) == RC
.LaneMask
)
163 for (MCSubRegIndexIterator
S(RR
.Reg
, &TRI
); S
.isValid(); ++S
)
164 if (RR
.Mask
== TRI
.getSubRegIndexLaneMask(S
.getSubRegIndex()))
165 return S
.getSubReg();
166 llvm_unreachable("Should have found a register");
170 const PhysicalRegisterInfo
&PRI
= DFG
.getPRI();
172 for (NodeId C
: Copies
) {
174 if (HasLimit
&& CpCount
>= CpLimit
)
177 auto SA
= DFG
.addr
<InstrNode
*>(C
);
178 auto FS
= CopyMap
.find(SA
.Id
);
179 if (FS
== CopyMap
.end())
182 EqualityMap
&EM
= FS
->second
;
183 for (NodeAddr
<DefNode
*> DA
: SA
.Addr
->members_if(DFG
.IsDef
, DFG
)) {
184 RegisterRef DR
= DA
.Addr
->getRegRef(DFG
);
185 auto FR
= EM
.find(DR
);
188 RegisterRef SR
= FR
->second
;
189 if (PRI
.equal_to(DR
, SR
))
192 auto &RDefSR
= RDefMap
[SR
];
193 NodeId RDefSR_SA
= RDefSR
[SA
.Id
];
195 for (NodeId N
= DA
.Addr
->getReachedUse(), NextN
; N
; N
= NextN
) {
196 auto UA
= DFG
.addr
<UseNode
*>(N
);
197 NextN
= UA
.Addr
->getSibling();
198 uint16_t F
= UA
.Addr
->getFlags();
199 if ((F
& NodeAttrs::PhiRef
) || (F
& NodeAttrs::Fixed
))
201 if (!PRI
.equal_to(UA
.Addr
->getRegRef(DFG
), DR
))
204 NodeAddr
<InstrNode
*> IA
= UA
.Addr
->getOwner(DFG
);
205 assert(DFG
.IsCode
<NodeAttrs::Stmt
>(IA
));
206 if (RDefSR
[IA
.Id
] != RDefSR_SA
)
209 MachineOperand
&Op
= UA
.Addr
->getOp();
213 dbgs() << "Can replace " << Print
<RegisterRef
>(DR
, DFG
)
214 << " with " << Print
<RegisterRef
>(SR
, DFG
) << " in "
215 << *NodeAddr
<StmtNode
*>(IA
).Addr
->getCode();
218 unsigned NewReg
= MinPhysReg(SR
);
221 DFG
.unlinkUse(UA
, false);
222 if (RDefSR_SA
!= 0) {
223 UA
.Addr
->linkToDef(UA
.Id
, DFG
.addr
<DefNode
*>(RDefSR_SA
));
225 UA
.Addr
->setReachingDef(0);
226 UA
.Addr
->setSibling(0);
231 if (HasLimit
&& CpCount
>= CpLimit
)
236 auto FC
= CopyMap
.find(IA
.Id
);
237 if (FC
!= CopyMap
.end()) {
238 // Update the EM map in the copy's entry.
239 auto &M
= FC
->second
;
241 if (!PRI
.equal_to(J
.second
, DR
))
247 } // for (N in reached-uses)
248 } // for (DA in defs)
249 } // for (C in Copies)