LLVM  4.0.0
HexagonRDFOpt.cpp
Go to the documentation of this file.
1 //===--- HexagonRDFOpt.cpp ------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "HexagonInstrInfo.h"
11 #include "HexagonSubtarget.h"
12 #include "RDFCopy.h"
13 #include "RDFDeadCode.h"
14 #include "RDFGraph.h"
15 #include "RDFLiveness.h"
16 #include "llvm/ADT/SetVector.h"
24 #include "llvm/Support/Format.h"
27 
28 using namespace llvm;
29 using namespace rdf;
30 
31 namespace llvm {
34 }
35 
36 namespace {
37  unsigned RDFCount = 0;
38  cl::opt<unsigned> RDFLimit("rdf-limit", cl::init(UINT_MAX));
39  cl::opt<bool> RDFDump("rdf-dump", cl::init(false));
40 
41  class HexagonRDFOpt : public MachineFunctionPass {
42  public:
43  HexagonRDFOpt() : MachineFunctionPass(ID) {
45  }
46  void getAnalysisUsage(AnalysisUsage &AU) const override {
49  AU.setPreservesAll();
51  }
52  StringRef getPassName() const override {
53  return "Hexagon RDF optimizations";
54  }
55  bool runOnMachineFunction(MachineFunction &MF) override;
56 
57  MachineFunctionProperties getRequiredProperties() const override {
60  }
61 
62  static char ID;
63 
64  private:
67  };
68 
69  char HexagonRDFOpt::ID = 0;
70 }
71 
72 INITIALIZE_PASS_BEGIN(HexagonRDFOpt, "rdfopt", "Hexagon RDF opt", false, false)
75 INITIALIZE_PASS_END(HexagonRDFOpt, "rdfopt", "Hexagon RDF opt", false, false)
76 
77 
78 namespace {
79 struct HexagonCP : public CopyPropagation {
80  HexagonCP(DataFlowGraph &G) : CopyPropagation(G) {}
81  bool interpretAsCopy(const MachineInstr *MI, EqualityMap &EM) override;
82 };
83 
84 
85 struct HexagonDCE : public DeadCodeElimination {
86  HexagonDCE(DataFlowGraph &G, MachineRegisterInfo &MRI)
87  : DeadCodeElimination(G, MRI) {}
88  bool rewrite(NodeAddr<InstrNode*> IA, SetVector<NodeId> &Remove);
89  void removeOperand(NodeAddr<InstrNode*> IA, unsigned OpNum);
90 
91  bool run();
92 };
93 } // end anonymous namespace
94 
95 
96 bool HexagonCP::interpretAsCopy(const MachineInstr *MI, EqualityMap &EM) {
97  auto mapRegs = [MI,&EM] (RegisterRef DstR, RegisterRef SrcR) -> void {
98  EM.insert(std::make_pair(DstR, SrcR));
99  };
100 
101  DataFlowGraph &DFG = getDFG();
102  unsigned Opc = MI->getOpcode();
103  switch (Opc) {
104  case Hexagon::A2_combinew: {
105  const MachineOperand &DstOp = MI->getOperand(0);
106  const MachineOperand &HiOp = MI->getOperand(1);
107  const MachineOperand &LoOp = MI->getOperand(2);
108  assert(DstOp.getSubReg() == 0 && "Unexpected subregister");
109  mapRegs(DFG.makeRegRef(DstOp.getReg(), Hexagon::isub_hi),
110  DFG.makeRegRef(HiOp.getReg(), HiOp.getSubReg()));
111  mapRegs(DFG.makeRegRef(DstOp.getReg(), Hexagon::isub_lo),
112  DFG.makeRegRef(LoOp.getReg(), LoOp.getSubReg()));
113  return true;
114  }
115  case Hexagon::A2_addi: {
116  const MachineOperand &A = MI->getOperand(2);
117  if (!A.isImm() || A.getImm() != 0)
118  return false;
120  }
121  case Hexagon::A2_tfr: {
122  const MachineOperand &DstOp = MI->getOperand(0);
123  const MachineOperand &SrcOp = MI->getOperand(1);
124  mapRegs(DFG.makeRegRef(DstOp.getReg(), DstOp.getSubReg()),
125  DFG.makeRegRef(SrcOp.getReg(), SrcOp.getSubReg()));
126  return true;
127  }
128  }
129 
130  return CopyPropagation::interpretAsCopy(MI, EM);
131 }
132 
133 
134 bool HexagonDCE::run() {
135  bool Collected = collect();
136  if (!Collected)
137  return false;
138 
139  const SetVector<NodeId> &DeadNodes = getDeadNodes();
140  const SetVector<NodeId> &DeadInstrs = getDeadInstrs();
141 
142  typedef DenseMap<NodeId,NodeId> RefToInstrMap;
143  RefToInstrMap R2I;
144  SetVector<NodeId> PartlyDead;
145  DataFlowGraph &DFG = getDFG();
146 
147  for (NodeAddr<BlockNode*> BA : DFG.getFunc().Addr->members(DFG)) {
148  for (auto TA : BA.Addr->members_if(DFG.IsCode<NodeAttrs::Stmt>, DFG)) {
149  NodeAddr<StmtNode*> SA = TA;
150  for (NodeAddr<RefNode*> RA : SA.Addr->members(DFG)) {
151  R2I.insert(std::make_pair(RA.Id, SA.Id));
152  if (DFG.IsDef(RA) && DeadNodes.count(RA.Id))
153  if (!DeadInstrs.count(SA.Id))
154  PartlyDead.insert(SA.Id);
155  }
156  }
157  }
158 
159 
160  // Nodes to remove.
161  SetVector<NodeId> Remove = DeadInstrs;
162 
163  bool Changed = false;
164  for (NodeId N : PartlyDead) {
165  auto SA = DFG.addr<StmtNode*>(N);
166  if (trace())
167  dbgs() << "Partly dead: " << *SA.Addr->getCode();
168  Changed |= rewrite(SA, Remove);
169  }
170 
171  return erase(Remove) || Changed;
172 }
173 
174 
175 void HexagonDCE::removeOperand(NodeAddr<InstrNode*> IA, unsigned OpNum) {
176  MachineInstr *MI = NodeAddr<StmtNode*>(IA).Addr->getCode();
177 
178  auto getOpNum = [MI] (MachineOperand &Op) -> unsigned {
179  for (unsigned i = 0, n = MI->getNumOperands(); i != n; ++i)
180  if (&MI->getOperand(i) == &Op)
181  return i;
182  llvm_unreachable("Invalid operand");
183  };
185  DataFlowGraph &DFG = getDFG();
186  NodeList Refs = IA.Addr->members(DFG);
187  for (NodeAddr<RefNode*> RA : Refs)
188  OpMap.insert(std::make_pair(RA.Id, getOpNum(RA.Addr->getOp())));
189 
190  MI->RemoveOperand(OpNum);
191 
192  for (NodeAddr<RefNode*> RA : Refs) {
193  unsigned N = OpMap[RA.Id];
194  if (N < OpNum)
195  RA.Addr->setRegRef(&MI->getOperand(N), DFG);
196  else if (N > OpNum)
197  RA.Addr->setRegRef(&MI->getOperand(N-1), DFG);
198  }
199 }
200 
201 
202 bool HexagonDCE::rewrite(NodeAddr<InstrNode*> IA, SetVector<NodeId> &Remove) {
203  if (!getDFG().IsCode<NodeAttrs::Stmt>(IA))
204  return false;
205  DataFlowGraph &DFG = getDFG();
206  MachineInstr &MI = *NodeAddr<StmtNode*>(IA).Addr->getCode();
207  auto &HII = static_cast<const HexagonInstrInfo&>(DFG.getTII());
208  if (HII.getAddrMode(MI) != HexagonII::PostInc)
209  return false;
210  unsigned Opc = MI.getOpcode();
211  unsigned OpNum, NewOpc;
212  switch (Opc) {
213  case Hexagon::L2_loadri_pi:
214  NewOpc = Hexagon::L2_loadri_io;
215  OpNum = 1;
216  break;
217  case Hexagon::L2_loadrd_pi:
218  NewOpc = Hexagon::L2_loadrd_io;
219  OpNum = 1;
220  break;
221  case Hexagon::V6_vL32b_pi:
222  NewOpc = Hexagon::V6_vL32b_ai;
223  OpNum = 1;
224  break;
225  case Hexagon::S2_storeri_pi:
226  NewOpc = Hexagon::S2_storeri_io;
227  OpNum = 0;
228  break;
229  case Hexagon::S2_storerd_pi:
230  NewOpc = Hexagon::S2_storerd_io;
231  OpNum = 0;
232  break;
233  case Hexagon::V6_vS32b_pi:
234  NewOpc = Hexagon::V6_vS32b_ai;
235  OpNum = 0;
236  break;
237  default:
238  return false;
239  }
240  auto IsDead = [this] (NodeAddr<DefNode*> DA) -> bool {
241  return getDeadNodes().count(DA.Id);
242  };
243  NodeList Defs;
244  MachineOperand &Op = MI.getOperand(OpNum);
245  for (NodeAddr<DefNode*> DA : IA.Addr->members_if(DFG.IsDef, DFG)) {
246  if (&DA.Addr->getOp() != &Op)
247  continue;
248  Defs = DFG.getRelatedRefs(IA, DA);
249  if (!all_of(Defs, IsDead))
250  return false;
251  break;
252  }
253 
254  // Mark all nodes in Defs for removal.
255  for (auto D : Defs)
256  Remove.insert(D.Id);
257 
258  if (trace())
259  dbgs() << "Rewriting: " << MI;
260  MI.setDesc(HII.get(NewOpc));
261  MI.getOperand(OpNum+2).setImm(0);
262  removeOperand(IA, OpNum);
263  if (trace())
264  dbgs() << " to: " << MI;
265 
266  return true;
267 }
268 
269 
270 bool HexagonRDFOpt::runOnMachineFunction(MachineFunction &MF) {
271  if (skipFunction(*MF.getFunction()))
272  return false;
273 
274  if (RDFLimit.getPosition()) {
275  if (RDFCount >= RDFLimit)
276  return false;
277  RDFCount++;
278  }
279 
280  MDT = &getAnalysis<MachineDominatorTree>();
281  const auto &MDF = getAnalysis<MachineDominanceFrontier>();
282  const auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
283  const auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
284  MRI = &MF.getRegInfo();
285  bool Changed;
286 
287  if (RDFDump)
288  MF.print(dbgs() << "Before " << getPassName() << "\n", nullptr);
289 
290  TargetOperandInfo TOI(HII);
291  DataFlowGraph G(MF, HII, HRI, *MDT, MDF, TOI);
292  // Dead phi nodes are necessary for copy propagation: we can add a use
293  // of a register in a block where it would need a phi node, but which
294  // was dead (and removed) during the graph build time.
296 
297  if (RDFDump)
298  dbgs() << "Starting copy propagation on: " << MF.getName() << '\n'
299  << PrintNode<FuncNode*>(G.getFunc(), G) << '\n';
300  HexagonCP CP(G);
301  CP.trace(RDFDump);
302  Changed = CP.run();
303 
304  if (RDFDump)
305  dbgs() << "Starting dead code elimination on: " << MF.getName() << '\n'
306  << PrintNode<FuncNode*>(G.getFunc(), G) << '\n';
307  HexagonDCE DCE(G, *MRI);
308  DCE.trace(RDFDump);
309  Changed |= DCE.run();
310 
311  if (Changed) {
312  if (RDFDump)
313  dbgs() << "Starting liveness recomputation on: " << MF.getName() << '\n';
314  Liveness LV(*MRI, G);
315  LV.trace(RDFDump);
316  LV.computeLiveIns();
317  LV.resetLiveIns();
318  LV.resetKills();
319  }
320 
321  if (RDFDump)
322  MF.print(dbgs() << "After " << getPassName() << "\n", nullptr);
323 
324  return false;
325 }
326 
327 
329  return new HexagonRDFOpt();
330 }
NodeList members(const DataFlowGraph &G) const
Definition: RDFGraph.cpp:541
void initializeHexagonRDFOptPass(PassRegistry &)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
size_t i
const TargetInstrInfo & getTII() const
Definition: RDFGraph.h:762
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:736
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:172
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:53
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
NodeList getRelatedRefs(NodeAddr< InstrNode * > IA, NodeAddr< RefNode * > RA) const
Definition: RDFGraph.cpp:1193
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
std::vector< NodeAddr< NodeBase * > > NodeList
Definition: RDFGraph.h:610
unsigned getNumOperands() const
Access to explicit operands of the instruction.
Definition: MachineInstr.h:277
void RemoveOperand(unsigned i)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:136
static bool IsDef(const NodeAddr< NodeBase * > BA)
Definition: RDFGraph.h:881
Function Alias Analysis false
int64_t getImm() const
NodeList members_if(Predicate P, const DataFlowGraph &G) const
Definition: RDFGraph.h:1002
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:273
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:395
unsigned const MachineRegisterInfo * MRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:279
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
static bool IsCode(const NodeAddr< NodeBase * > BA)
Definition: RDFGraph.h:876
unsigned getSubReg() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint32_t NodeId
Definition: RDFGraph.h:262
virtual bool interpretAsCopy(const MachineInstr *MI, EqualityMap &EM)
Definition: RDFCopy.cpp:29
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
FunctionPass * createHexagonRDFOpt()
MachineOperand class - Representation of each machine instruction operand.
const DataFlowGraph & G
Definition: RDFGraph.cpp:206
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:50
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
NodeAddr< FuncNode * > getFunc() const
Definition: RDFGraph.h:760
void setPreservesAll()
Set by analyses that do not transform their input at all.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
Definition: MachineInstr.h:52
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
Definition: SetVector.h:205
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
RegisterRef makeRegRef(unsigned Reg, unsigned Sub) const
Definition: RDFGraph.cpp:1073
#define N
void build(unsigned Options=BuildOptions::None)
Definition: RDFGraph.cpp:989
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream...
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineInstr * getCode() const
Definition: RDFGraph.h:721
A vector that has set insertion semantics.
Definition: SetVector.h:41
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:239
NodeAddr< T > addr(NodeId N) const
Definition: RDFGraph.h:756
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:40
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Properties which a MachineFunction may have at a given point in time.