LLVM 18.0.0git
HexagonRDFOpt.cpp
Go to the documentation of this file.
1//===- HexagonRDFOpt.cpp --------------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "HexagonInstrInfo.h"
10#include "HexagonSubtarget.h"
12#include "RDFCopy.h"
13#include "RDFDeadCode.h"
14#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SetVector.h"
28#include "llvm/Pass.h"
31#include "llvm/Support/Debug.h"
34#include <cassert>
35#include <limits>
36#include <utility>
37
38using namespace llvm;
39using namespace rdf;
40
41namespace llvm {
42
45
46} // end namespace llvm
47
48static unsigned RDFCount = 0;
49
51 RDFLimit("hexagon-rdf-limit",
52 cl::init(std::numeric_limits<unsigned>::max()));
53static cl::opt<bool> RDFDump("hexagon-rdf-dump", cl::Hidden);
54static cl::opt<bool> RDFTrackReserved("hexagon-rdf-track-reserved", cl::Hidden);
55
56namespace {
57
58 class HexagonRDFOpt : public MachineFunctionPass {
59 public:
60 HexagonRDFOpt() : MachineFunctionPass(ID) {}
61
62 void getAnalysisUsage(AnalysisUsage &AU) const override {
65 AU.setPreservesAll();
67 }
68
69 StringRef getPassName() const override {
70 return "Hexagon RDF optimizations";
71 }
72
73 bool runOnMachineFunction(MachineFunction &MF) override;
74
77 MachineFunctionProperties::Property::NoVRegs);
78 }
79
80 static char ID;
81
82 private:
85 };
86
87struct HexagonCP : public CopyPropagation {
88 HexagonCP(DataFlowGraph &G) : CopyPropagation(G) {}
89
90 bool interpretAsCopy(const MachineInstr *MI, EqualityMap &EM) override;
91};
92
93struct HexagonDCE : public DeadCodeElimination {
96
98 void removeOperand(NodeAddr<InstrNode*> IA, unsigned OpNum);
99
100 bool run();
101};
102
103} // end anonymous namespace
104
105char HexagonRDFOpt::ID = 0;
106
107INITIALIZE_PASS_BEGIN(HexagonRDFOpt, "hexagon-rdf-opt",
108 "Hexagon RDF optimizations", false, false)
111INITIALIZE_PASS_END(HexagonRDFOpt, "hexagon-rdf-opt",
112 "Hexagon RDF optimizations", false, false)
113
114bool HexagonCP::interpretAsCopy(const MachineInstr *MI, EqualityMap &EM) {
115 auto mapRegs = [&EM] (RegisterRef DstR, RegisterRef SrcR) -> void {
116 EM.insert(std::make_pair(DstR, SrcR));
117 };
118
119 DataFlowGraph &DFG = getDFG();
120 unsigned Opc = MI->getOpcode();
121 switch (Opc) {
122 case Hexagon::A2_combinew: {
123 const MachineOperand &DstOp = MI->getOperand(0);
124 const MachineOperand &HiOp = MI->getOperand(1);
125 const MachineOperand &LoOp = MI->getOperand(2);
126 assert(DstOp.getSubReg() == 0 && "Unexpected subregister");
127 mapRegs(DFG.makeRegRef(DstOp.getReg(), Hexagon::isub_hi),
128 DFG.makeRegRef(HiOp.getReg(), HiOp.getSubReg()));
129 mapRegs(DFG.makeRegRef(DstOp.getReg(), Hexagon::isub_lo),
130 DFG.makeRegRef(LoOp.getReg(), LoOp.getSubReg()));
131 return true;
132 }
133 case Hexagon::A2_addi: {
134 const MachineOperand &A = MI->getOperand(2);
135 if (!A.isImm() || A.getImm() != 0)
136 return false;
137 [[fallthrough]];
138 }
139 case Hexagon::A2_tfr: {
140 const MachineOperand &DstOp = MI->getOperand(0);
141 const MachineOperand &SrcOp = MI->getOperand(1);
142 mapRegs(DFG.makeRegRef(DstOp.getReg(), DstOp.getSubReg()),
143 DFG.makeRegRef(SrcOp.getReg(), SrcOp.getSubReg()));
144 return true;
145 }
146 }
147
148 return CopyPropagation::interpretAsCopy(MI, EM);
149}
150
151bool HexagonDCE::run() {
152 bool Collected = collect();
153 if (!Collected)
154 return false;
155
156 const SetVector<NodeId> &DeadNodes = getDeadNodes();
157 const SetVector<NodeId> &DeadInstrs = getDeadInstrs();
158
159 using RefToInstrMap = DenseMap<NodeId, NodeId>;
160
161 RefToInstrMap R2I;
162 SetVector<NodeId> PartlyDead;
163 DataFlowGraph &DFG = getDFG();
164
165 for (NodeAddr<BlockNode*> BA : DFG.getFunc().Addr->members(DFG)) {
166 for (auto TA : BA.Addr->members_if(DFG.IsCode<NodeAttrs::Stmt>, DFG)) {
168 for (NodeAddr<RefNode*> RA : SA.Addr->members(DFG)) {
169 R2I.insert(std::make_pair(RA.Id, SA.Id));
170 if (DFG.IsDef(RA) && DeadNodes.count(RA.Id))
171 if (!DeadInstrs.count(SA.Id))
172 PartlyDead.insert(SA.Id);
173 }
174 }
175 }
176
177 // Nodes to remove.
178 SetVector<NodeId> Remove = DeadInstrs;
179
180 bool Changed = false;
181 for (NodeId N : PartlyDead) {
182 auto SA = DFG.addr<StmtNode*>(N);
183 if (trace())
184 dbgs() << "Partly dead: " << *SA.Addr->getCode();
185 Changed |= rewrite(SA, Remove);
186 }
187
188 return erase(Remove) || Changed;
189}
190
191void HexagonDCE::removeOperand(NodeAddr<InstrNode*> IA, unsigned OpNum) {
192 MachineInstr *MI = NodeAddr<StmtNode*>(IA).Addr->getCode();
193
194 auto getOpNum = [MI] (MachineOperand &Op) -> unsigned {
195 for (unsigned i = 0, n = MI->getNumOperands(); i != n; ++i)
196 if (&MI->getOperand(i) == &Op)
197 return i;
198 llvm_unreachable("Invalid operand");
199 };
201 DataFlowGraph &DFG = getDFG();
202 NodeList Refs = IA.Addr->members(DFG);
203 for (NodeAddr<RefNode*> RA : Refs)
204 OpMap.insert(std::make_pair(RA.Id, getOpNum(RA.Addr->getOp())));
205
206 MI->removeOperand(OpNum);
207
208 for (NodeAddr<RefNode*> RA : Refs) {
209 unsigned N = OpMap[RA.Id];
210 if (N < OpNum)
211 RA.Addr->setRegRef(&MI->getOperand(N), DFG);
212 else if (N > OpNum)
213 RA.Addr->setRegRef(&MI->getOperand(N-1), DFG);
214 }
215}
216
217bool HexagonDCE::rewrite(NodeAddr<InstrNode*> IA, SetVector<NodeId> &Remove) {
218 if (!getDFG().IsCode<NodeAttrs::Stmt>(IA))
219 return false;
220 DataFlowGraph &DFG = getDFG();
221 MachineInstr &MI = *NodeAddr<StmtNode*>(IA).Addr->getCode();
222 auto &HII = static_cast<const HexagonInstrInfo&>(DFG.getTII());
223 if (HII.getAddrMode(MI) != HexagonII::PostInc)
224 return false;
225 unsigned Opc = MI.getOpcode();
226 unsigned OpNum, NewOpc;
227 switch (Opc) {
228 case Hexagon::L2_loadri_pi:
229 NewOpc = Hexagon::L2_loadri_io;
230 OpNum = 1;
231 break;
232 case Hexagon::L2_loadrd_pi:
233 NewOpc = Hexagon::L2_loadrd_io;
234 OpNum = 1;
235 break;
236 case Hexagon::V6_vL32b_pi:
237 NewOpc = Hexagon::V6_vL32b_ai;
238 OpNum = 1;
239 break;
240 case Hexagon::S2_storeri_pi:
241 NewOpc = Hexagon::S2_storeri_io;
242 OpNum = 0;
243 break;
244 case Hexagon::S2_storerd_pi:
245 NewOpc = Hexagon::S2_storerd_io;
246 OpNum = 0;
247 break;
248 case Hexagon::V6_vS32b_pi:
249 NewOpc = Hexagon::V6_vS32b_ai;
250 OpNum = 0;
251 break;
252 default:
253 return false;
254 }
255 auto IsDead = [this] (NodeAddr<DefNode*> DA) -> bool {
256 return getDeadNodes().count(DA.Id);
257 };
258 NodeList Defs;
259 MachineOperand &Op = MI.getOperand(OpNum);
260 for (NodeAddr<DefNode*> DA : IA.Addr->members_if(DFG.IsDef, DFG)) {
261 if (&DA.Addr->getOp() != &Op)
262 continue;
263 Defs = DFG.getRelatedRefs(IA, DA);
264 if (!llvm::all_of(Defs, IsDead))
265 return false;
266 break;
267 }
268
269 // Mark all nodes in Defs for removal.
270 for (auto D : Defs)
271 Remove.insert(D.Id);
272
273 if (trace())
274 dbgs() << "Rewriting: " << MI;
275 MI.setDesc(HII.get(NewOpc));
276 MI.getOperand(OpNum+2).setImm(0);
277 removeOperand(IA, OpNum);
278 if (trace())
279 dbgs() << " to: " << MI;
280
281 return true;
282}
283
284bool HexagonRDFOpt::runOnMachineFunction(MachineFunction &MF) {
285 if (skipFunction(MF.getFunction()))
286 return false;
287
288 if (RDFLimit.getPosition()) {
289 if (RDFCount >= RDFLimit)
290 return false;
291 RDFCount++;
292 }
293
294 MDT = &getAnalysis<MachineDominatorTree>();
295 const auto &MDF = getAnalysis<MachineDominanceFrontier>();
296 const auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
297 const auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
298 MRI = &MF.getRegInfo();
299 bool Changed;
300
301 if (RDFDump)
302 MF.print(dbgs() << "Before " << getPassName() << "\n", nullptr);
303
304 DataFlowGraph G(MF, HII, HRI, *MDT, MDF);
305 // Dead phi nodes are necessary for copy propagation: we can add a use
306 // of a register in a block where it would need a phi node, but which
307 // was dead (and removed) during the graph build time.
312 G.build(Cfg);
313
314 if (RDFDump)
315 dbgs() << "Starting copy propagation on: " << MF.getName() << '\n'
316 << PrintNode<FuncNode*>(G.getFunc(), G) << '\n';
317 HexagonCP CP(G);
318 CP.trace(RDFDump);
319 Changed = CP.run();
320
321 if (RDFDump)
322 dbgs() << "Starting dead code elimination on: " << MF.getName() << '\n'
323 << PrintNode<FuncNode*>(G.getFunc(), G) << '\n';
324 HexagonDCE DCE(G, *MRI);
325 DCE.trace(RDFDump);
326 Changed |= DCE.run();
327
328 if (Changed) {
329 if (RDFDump) {
330 dbgs() << "Starting liveness recomputation on: " << MF.getName() << '\n'
331 << PrintNode<FuncNode*>(G.getFunc(), G) << '\n';
332 }
333 Liveness LV(*MRI, G);
334 LV.trace(RDFDump);
335 LV.computeLiveIns();
336 LV.resetLiveIns();
337 LV.resetKills();
338 }
339
340 if (RDFDump)
341 MF.print(dbgs() << "After " << getPassName() << "\n", nullptr);
342
343 return false;
344}
345
347 return new HexagonRDFOpt();
348}
unsigned const MachineRegisterInfo * MRI
aarch64 promote const
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseMap class.
static cl::opt< bool > RDFTrackReserved("hexagon-rdf-track-reserved", cl::Hidden)
static cl::opt< unsigned > RDFLimit("hexagon-rdf-limit", cl::init(std::numeric_limits< unsigned >::max()))
hexagon rdf Hexagon RDF optimizations
hexagon rdf opt
static unsigned RDFCount
static cl::opt< bool > RDFDump("hexagon-rdf-dump", cl::Hidden)
IRTranslator LLVM IR MI
#define G(x, y, z)
Definition: MD5.cpp:56
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
static bool rewrite(Function &F)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool IsDead
SI optimize exec mask operations pre RA
This file contains some templates that are useful if you are working with the STL at all.
This file implements a set that has insertion order iteration characteristics.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
This class represents an Operation in the Expression.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:220
Register getReg() const
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
Representation of each machine instruction.
Definition: MachineInstr.h:68
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:37
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
A vector that has set insertion semantics.
Definition: SetVector.h:57
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
Definition: SetVector.h:264
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:162
Register getReg() const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1727
void initializeHexagonRDFOptPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
DWARFExpression::Operation Op
FunctionPass * createHexagonRDFOpt()
#define N
NodeList members(const DataFlowGraph &G) const
Definition: RDFGraph.cpp:520
RegisterRef makeRegRef(unsigned Reg, unsigned Sub) const
Definition: RDFGraph.cpp:985
static bool IsDef(const Node BA)
Definition: RDFGraph.h:825
Func getFunc() const
Definition: RDFGraph.h:693
NodeList getRelatedRefs(Instr IA, Ref RA) const
Definition: RDFGraph.cpp:1136
const TargetInstrInfo & getTII() const
Definition: RDFGraph.h:695
static bool IsCode(const Node BA)
Definition: RDFGraph.h:821
NodeAddr< T > addr(NodeId N) const
Definition: RDFGraph.h:689