blob: fd68fdff43de274169409119859a8f4315c76b88 [file] [log] [blame]
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +00001//===--- HexagonOptAddrMode.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// This implements a Hexagon-specific pass to optimize addressing mode for
10// load/store instructions.
11//===----------------------------------------------------------------------===//
12
13#define DEBUG_TYPE "opt-addr-mode"
14
15#include "HexagonTargetMachine.h"
16#include "RDFGraph.h"
17#include "RDFLiveness.h"
18
19#include "llvm/ADT/DenseSet.h"
20#include "llvm/CodeGen/MachineBasicBlock.h"
21#include "llvm/CodeGen/MachineDominanceFrontier.h"
22#include "llvm/CodeGen/MachineDominators.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
25#include "llvm/CodeGen/MachineRegisterInfo.h"
26#include "llvm/CodeGen/Passes.h"
27#include "llvm/Support/CommandLine.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/raw_ostream.h"
30#include "llvm/Target/TargetInstrInfo.h"
31#include "llvm/Target/TargetMachine.h"
32#include "llvm/Target/TargetRegisterInfo.h"
33
34static cl::opt<int> CodeGrowthLimit("hexagon-amode-growth-limit",
35 cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode "
36 "optimization"));
37
38using namespace llvm;
39using namespace rdf;
40
41namespace llvm {
42 FunctionPass *createHexagonOptAddrMode();
43 void initializeHexagonOptAddrModePass(PassRegistry &);
44}
45
46namespace {
47class HexagonOptAddrMode : public MachineFunctionPass {
48public:
49 static char ID;
50 HexagonOptAddrMode()
51 : MachineFunctionPass(ID), HII(0), MDT(0), DFG(0), LV(0) {
52 PassRegistry &R = *PassRegistry::getPassRegistry();
53 initializeHexagonOptAddrModePass(R);
54 }
55 const char *getPassName() const override {
56 return "Optimize addressing mode of load/store";
57 }
58 void getAnalysisUsage(AnalysisUsage &AU) const override {
59 MachineFunctionPass::getAnalysisUsage(AU);
60 AU.addRequired<MachineDominatorTree>();
61 AU.addRequired<MachineDominanceFrontier>();
62 AU.setPreservesAll();
63 }
64 bool runOnMachineFunction(MachineFunction &MF) override;
65
66private:
67 typedef DenseSet<MachineInstr *> MISetType;
68 typedef DenseMap<MachineInstr *, bool> InstrEvalMap;
69 const HexagonInstrInfo *HII;
70 MachineDominatorTree *MDT;
71 DataFlowGraph *DFG;
72 DataFlowGraph::DefStackMap DefM;
73 std::map<RegisterRef, std::map<NodeId, NodeId>> RDefMap;
74 Liveness *LV;
75 MISetType Deleted;
76
77 bool processBlock(NodeAddr<BlockNode *> BA);
78 bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
79 NodeAddr<UseNode *> UseN, unsigned UseMOnum);
80 bool analyzeUses(unsigned DefR, const NodeList &UNodeList,
81 InstrEvalMap &InstrEvalResult, short &SizeInc);
82 bool hasRepForm(MachineInstr *MI, unsigned TfrDefR);
83 MachineInstr *getReachedDefMI(NodeAddr<StmtNode *> SN, unsigned OffsetReg,
84 bool &HasReachingDef);
85 bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr *MI,
86 const NodeList &UNodeList);
87 void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList);
88 bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList);
89 short getBaseWithLongOffset(const MachineInstr *MI) const;
90 void updateMap(NodeAddr<InstrNode *> IA);
91 bool constructDefMap(MachineBasicBlock *B);
92 bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
93 unsigned ImmOpNum);
94 bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum);
95 bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,
96 const MachineOperand &ImmOp, unsigned ImmOpNum);
97};
98}
99
100char HexagonOptAddrMode::ID = 0;
101
102INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "opt-amode",
103 "Optimize addressing mode", false, false)
104INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
105INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)
106INITIALIZE_PASS_END(HexagonOptAddrMode, "opt-amode", "Optimize addressing mode",
107 false, false)
108
109bool HexagonOptAddrMode::hasRepForm(MachineInstr *MI, unsigned TfrDefR) {
110 const MCInstrDesc &MID = MI->getDesc();
111
112 if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(*MI))
113 return false;
114
115 if (MID.mayStore()) {
116 MachineOperand StOp = MI->getOperand(MI->getNumOperands() - 1);
117 if (StOp.isReg() && StOp.getReg() == TfrDefR)
118 return false;
119 }
120
121 if (HII->getAddrMode(MI) == HexagonII::BaseRegOffset)
122 // Tranform to Absolute plus register offset.
123 return (HII->getBaseWithLongOffset(MI) >= 0);
124 else if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset)
125 // Tranform to absolute addressing mode.
126 return (HII->getAbsoluteForm(MI) >= 0);
127
128 return false;
129}
130
131MachineInstr *HexagonOptAddrMode::getReachedDefMI(NodeAddr<StmtNode *> SN,
132 unsigned OffsetReg,
133 bool &HasReachingDef) {
134 MachineInstr *ReachedDefMI = NULL;
135 NodeId RD = 0;
136 for (NodeAddr<UseNode *> UN : SN.Addr->members_if(DFG->IsUse, *DFG)) {
137 RegisterRef UR = UN.Addr->getRegRef();
138 if (OffsetReg == UR.Reg) {
139 RD = UN.Addr->getReachingDef();
140 if (!RD)
141 continue;
142 HasReachingDef = true;
143 }
144 }
145 if (HasReachingDef) {
146 NodeAddr<DefNode *> RDN = DFG->addr<DefNode *>(RD);
147 NodeAddr<StmtNode *> ReachingIA = RDN.Addr->getOwner(*DFG);
148 DEBUG(dbgs() << "\t\t\t[Def Node]: "
149 << Print<NodeAddr<InstrNode *>>(ReachingIA, *DFG) << "\n");
150 NodeId ReachedID = RDN.Addr->getReachedDef();
151 if (!ReachedID)
152 return ReachedDefMI;
153
154 NodeAddr<DefNode *> ReachedDN = DFG->addr<DefNode *>(ReachedID);
155 NodeAddr<StmtNode *> ReachedIA = ReachedDN.Addr->getOwner(*DFG);
156 DEBUG(dbgs() << "\t\t\t[Reached Def Node]: "
157 << Print<NodeAddr<InstrNode *>>(ReachedIA, *DFG) << "\n");
158 ReachedDefMI = ReachedIA.Addr->getCode();
159 DEBUG(dbgs() << "\nReached Def MI === " << *ReachedDefMI << "\n");
160 }
161 return ReachedDefMI;
162}
163
164// Check if addasl instruction can be removed. This is possible only
165// if it's feeding to only load/store instructions with base + register
166// offset as these instruction can be tranformed to use 'absolute plus
167// shifted register offset'.
168// ex:
169// Rs = ##foo
170// Rx = addasl(Rs, Rt, #2)
171// Rd = memw(Rx + #28)
172// Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)
173
174bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN,
175 MachineInstr *MI,
176 const NodeList &UNodeList) {
177 // check offset size in addasl. if 'offset > 3' return false
178 const MachineOperand &OffsetOp = MI->getOperand(3);
179 if (!OffsetOp.isImm() || OffsetOp.getImm() > 3)
180 return false;
181
182 unsigned OffsetReg = MI->getOperand(2).getReg();
183 RegisterRef OffsetRR;
184 NodeId OffsetRegRD = 0;
185 for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {
186 RegisterRef RR = UA.Addr->getRegRef();
187 if (OffsetReg == RR.Reg) {
188 OffsetRR = RR;
189 OffsetRegRD = UA.Addr->getReachingDef();
190 }
191 }
192
193 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
194 NodeAddr<UseNode *> UA = *I;
195 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
196 if ((UA.Addr->getFlags() & NodeAttrs::PhiRef) ||
197 RDefMap[OffsetRR][IA.Id] != OffsetRegRD)
198 return false;
199
200 MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode();
201 NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);
202 // Reaching Def to an offset register can't be a phi.
203 if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&
204 MI->getParent() != UseMI->getParent())
205 return false;
206
207 const MCInstrDesc &UseMID = UseMI->getDesc();
208 if ((!UseMID.mayLoad() && !UseMID.mayStore()) ||
209 HII->getAddrMode(UseMI) != HexagonII::BaseImmOffset ||
210 getBaseWithLongOffset(UseMI) < 0)
211 return false;
212
213 // Addasl output can't be a store value.
214 if (UseMID.mayStore() && UseMI->getOperand(2).isReg() &&
215 UseMI->getOperand(2).getReg() == MI->getOperand(0).getReg())
216 return false;
217
218 for (auto &Mo : UseMI->operands())
219 if (Mo.isFI())
220 return false;
221 }
222 return true;
223}
224
225bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,
226 NodeList &UNodeList) {
227 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
228 NodeAddr<UseNode *> UN = *I;
229 RegisterRef UR = UN.Addr->getRegRef();
230 NodeSet Visited, Defs;
231 const auto &ReachingDefs = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
232 if (ReachingDefs.size() > 1) {
233 DEBUG(dbgs() << "*** Multiple Reaching Defs found!!! *** \n");
234 for (auto DI : ReachingDefs) {
235 NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);
236 NodeAddr<StmtNode *> tempIA = DA.Addr->getOwner(*DFG);
237 DEBUG(dbgs() << "\t\t[Reaching Def]: "
238 << Print<NodeAddr<InstrNode *>>(tempIA, *DFG) << "\n");
239 }
240 return false;
241 }
242 }
243 return true;
244}
245
246void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,
247 NodeList &UNodeList) {
248 for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {
249 DEBUG(dbgs() << "\t\t[DefNode]: " << Print<NodeAddr<DefNode *>>(DA, *DFG)
250 << "\n");
251 RegisterRef DR = DA.Addr->getRegRef();
252 auto UseSet = LV->getAllReachedUses(DR, DA);
253
254 for (auto UI : UseSet) {
255 NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);
256 NodeAddr<StmtNode *> tempIA = UA.Addr->getOwner(*DFG);
257 DEBUG(dbgs() << "\t\t\t[Reached Use]: "
258 << Print<NodeAddr<InstrNode *>>(tempIA, *DFG) << "\n");
259
260 if (UA.Addr->getFlags() & NodeAttrs::PhiRef) {
261 NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);
262 NodeId id = PA.Id;
263 const Liveness::RefMap &phiUse = LV->getRealUses(id);
264 DEBUG(dbgs() << "\t\t\t\tphi real Uses"
265 << Print<Liveness::RefMap>(phiUse, *DFG) << "\n");
266 if (phiUse.size() > 0) {
267 for (auto I : phiUse) {
268 if (DR != I.first)
269 continue;
270 auto phiUseSet = I.second;
271 for (auto phiUI : phiUseSet) {
272 NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI);
273 UNodeList.push_back(phiUA);
274 }
275 }
276 }
277 } else
278 UNodeList.push_back(UA);
279 }
280 }
281}
282
283bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,
284 const NodeList &UNodeList,
285 InstrEvalMap &InstrEvalResult,
286 short &SizeInc) {
287 bool KeepTfr = false;
288 bool HasRepInstr = false;
289 InstrEvalResult.clear();
290
291 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
292 bool CanBeReplaced = false;
293 NodeAddr<UseNode *> UN = *I;
294 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
295 MachineInstr *MI = SN.Addr->getCode();
296 const MCInstrDesc &MID = MI->getDesc();
297 if ((MID.mayLoad() || MID.mayStore())) {
298 if (!hasRepForm(MI, tfrDefR)) {
299 KeepTfr = true;
300 continue;
301 }
302 SizeInc++;
303 CanBeReplaced = true;
304 } else if (MI->getOpcode() == Hexagon::S2_addasl_rrri) {
305 NodeList AddaslUseList;
306
307 DEBUG(dbgs() << "\nGetting ReachedUses for === " << *MI << "\n");
308 getAllRealUses(SN, AddaslUseList);
309 // Process phi nodes.
310 if (allValidCandidates(SN, AddaslUseList) &&
311 canRemoveAddasl(SN, MI, AddaslUseList)) {
312 SizeInc += AddaslUseList.size();
313 SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed.
314 CanBeReplaced = true;
315 } else
316 SizeInc++;
317 } else
318 // Currently, only load/store and addasl are handled.
319 // Some other instructions to consider -
320 // A2_add -> A2_addi
321 // M4_mpyrr_addr -> M4_mpyrr_addi
322 KeepTfr = true;
323
324 InstrEvalResult[MI] = CanBeReplaced;
325 HasRepInstr |= CanBeReplaced;
326 }
327
328 // Reduce total size by 2 if original tfr can be deleted.
329 if (!KeepTfr)
330 SizeInc -= 2;
331
332 return HasRepInstr;
333}
334
335bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,
336 unsigned ImmOpNum) {
337 bool Changed = false;
338 MachineBasicBlock *BB = OldMI->getParent();
339 auto UsePos = MachineBasicBlock::iterator(OldMI);
340 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
341 ++InsertPt;
342 unsigned OpStart;
343 unsigned OpEnd = OldMI->getNumOperands();
344 MachineInstrBuilder MIB;
345
346 if (ImmOpNum == 1) {
347 if (HII->getAddrMode(OldMI) == HexagonII::BaseRegOffset) {
348 short NewOpCode = HII->getBaseWithLongOffset(OldMI);
349 assert(NewOpCode >= 0 && "Invalid New opcode\n");
350 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
351 MIB.addOperand(OldMI->getOperand(0));
352 MIB.addOperand(OldMI->getOperand(2));
353 MIB.addOperand(OldMI->getOperand(3));
354 MIB.addOperand(ImmOp);
355 OpStart = 4;
356 Changed = true;
357 } else if (HII->getAddrMode(OldMI) == HexagonII::BaseImmOffset) {
358 short NewOpCode = HII->getAbsoluteForm(OldMI);
359 assert(NewOpCode >= 0 && "Invalid New opcode\n");
360 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))
361 .addOperand(OldMI->getOperand(0));
362 const GlobalValue *GV = ImmOp.getGlobal();
363 int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm();
364
365 MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
366 OpStart = 3;
367 Changed = true;
368 } else
369 Changed = false;
370
371 DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
372 DEBUG(dbgs() << "[TO]: " << MIB << "\n");
373 } else if (ImmOpNum == 2 && OldMI->getOperand(3).getImm() == 0) {
374 short NewOpCode = HII->xformRegToImmOffset(OldMI);
375 assert(NewOpCode >= 0 && "Invalid New opcode\n");
376 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
377 MIB.addOperand(OldMI->getOperand(0));
378 MIB.addOperand(OldMI->getOperand(1));
379 MIB.addOperand(ImmOp);
380 OpStart = 4;
381 Changed = true;
382 DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
383 DEBUG(dbgs() << "[TO]: " << MIB << "\n");
384 }
385
386 if (Changed)
387 for (unsigned i = OpStart; i < OpEnd; ++i)
388 MIB.addOperand(OldMI->getOperand(i));
389
390 return Changed;
391}
392
393bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
394 unsigned ImmOpNum) {
395 bool Changed = false;
396 unsigned OpStart;
397 unsigned OpEnd = OldMI->getNumOperands();
398 MachineBasicBlock *BB = OldMI->getParent();
399 auto UsePos = MachineBasicBlock::iterator(OldMI);
400 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
401 ++InsertPt;
402 MachineInstrBuilder MIB;
403 if (ImmOpNum == 0) {
404 if (HII->getAddrMode(OldMI) == HexagonII::BaseRegOffset) {
405 short NewOpCode = HII->getBaseWithLongOffset(OldMI);
406 assert(NewOpCode >= 0 && "Invalid New opcode\n");
407 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
408 MIB.addOperand(OldMI->getOperand(1));
409 MIB.addOperand(OldMI->getOperand(2));
410 MIB.addOperand(ImmOp);
411 MIB.addOperand(OldMI->getOperand(3));
412 OpStart = 4;
413 } else if (HII->getAddrMode(OldMI) == HexagonII::BaseImmOffset) {
414 short NewOpCode = HII->getAbsoluteForm(OldMI);
415 assert(NewOpCode >= 0 && "Invalid New opcode\n");
416 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
417 const GlobalValue *GV = ImmOp.getGlobal();
418 int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm();
419 MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
420 MIB.addOperand(OldMI->getOperand(2));
421 OpStart = 3;
422 }
423 Changed = true;
424 DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
425 DEBUG(dbgs() << "[TO]: " << MIB << "\n");
426 } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) {
427 short NewOpCode = HII->xformRegToImmOffset(OldMI);
428 assert(NewOpCode >= 0 && "Invalid New opcode\n");
429 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
430 MIB.addOperand(OldMI->getOperand(0));
431 MIB.addOperand(ImmOp);
432 MIB.addOperand(OldMI->getOperand(1));
433 OpStart = 2;
434 Changed = true;
435 DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
436 DEBUG(dbgs() << "[TO]: " << MIB << "\n");
437 }
438 if (Changed)
439 for (unsigned i = OpStart; i < OpEnd; ++i)
440 MIB.addOperand(OldMI->getOperand(i));
441
442 return Changed;
443}
444
445short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr *MI) const {
446 if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) {
447 short TempOpCode = HII->getBaseWithRegOffset(MI);
448 return HII->getBaseWithLongOffset(TempOpCode);
449 } else
450 return HII->getBaseWithLongOffset(MI);
451}
452
453bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,
454 MachineInstr *AddAslMI,
455 const MachineOperand &ImmOp,
456 unsigned ImmOpNum) {
457 NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);
458
459 DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");
460
461 NodeList UNodeList;
462 getAllRealUses(SA, UNodeList);
463
464 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
465 NodeAddr<UseNode *> UseUN = *I;
466 assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) &&
467 "Can't transform this 'AddAsl' instruction!");
468
469 NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);
470 DEBUG(dbgs() << "[InstrNode]: " << Print<NodeAddr<InstrNode *>>(UseIA, *DFG)
471 << "\n");
472 MachineInstr *UseMI = UseIA.Addr->getCode();
473 DEBUG(dbgs() << "[MI <BB#" << UseMI->getParent()->getNumber()
474 << ">]: " << *UseMI << "\n");
475 const MCInstrDesc &UseMID = UseMI->getDesc();
476 assert(HII->getAddrMode(UseMI) == HexagonII::BaseImmOffset);
477
478 auto UsePos = MachineBasicBlock::iterator(UseMI);
479 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
480 short NewOpCode = getBaseWithLongOffset(UseMI);
481 assert(NewOpCode >= 0 && "Invalid New opcode\n");
482
483 unsigned OpStart;
484 unsigned OpEnd = UseMI->getNumOperands();
485
486 MachineBasicBlock *BB = UseMI->getParent();
487 MachineInstrBuilder MIB =
488 BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode));
489 // change mem(Rs + # ) -> mem(Rt << # + ##)
490 if (UseMID.mayLoad()) {
491 MIB.addOperand(UseMI->getOperand(0));
492 MIB.addOperand(AddAslMI->getOperand(2));
493 MIB.addOperand(AddAslMI->getOperand(3));
494 const GlobalValue *GV = ImmOp.getGlobal();
495 MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm(),
496 ImmOp.getTargetFlags());
497 OpStart = 3;
498 } else if (UseMID.mayStore()) {
499 MIB.addOperand(AddAslMI->getOperand(2));
500 MIB.addOperand(AddAslMI->getOperand(3));
501 const GlobalValue *GV = ImmOp.getGlobal();
502 MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm(),
503 ImmOp.getTargetFlags());
504 MIB.addOperand(UseMI->getOperand(2));
505 OpStart = 3;
506 } else
507 llvm_unreachable("Unhandled instruction");
508
509 for (unsigned i = OpStart; i < OpEnd; ++i)
510 MIB.addOperand(UseMI->getOperand(i));
511
512 Deleted.insert(UseMI);
513 }
514
515 return true;
516}
517
518bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
519 NodeAddr<UseNode *> UseN,
520 unsigned UseMOnum) {
521 const MachineOperand ImmOp = TfrMI->getOperand(1);
522 const MCInstrDesc &MID = UseMI->getDesc();
523 unsigned Changed = false;
524 if (MID.mayLoad())
525 Changed = changeLoad(UseMI, ImmOp, UseMOnum);
526 else if (MID.mayStore())
527 Changed = changeStore(UseMI, ImmOp, UseMOnum);
528 else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri)
529 Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
530
531 if (Changed)
532 Deleted.insert(UseMI);
533
534 return Changed;
535}
536
537bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {
538 bool Changed = false;
539
540 for (auto IA : BA.Addr->members(*DFG)) {
541 if (!DFG->IsCode<NodeAttrs::Stmt>(IA))
542 continue;
543
544 NodeAddr<StmtNode *> SA = IA;
545 MachineInstr *MI = SA.Addr->getCode();
546 if (MI->getOpcode() != Hexagon::A2_tfrsi ||
547 !MI->getOperand(1).isGlobal())
548 continue;
549
550 DEBUG(dbgs() << "[Analyzing A2_tfrsi]: " << *MI << "\n");
551 DEBUG(dbgs() << "\t[InstrNode]: " << Print<NodeAddr<InstrNode *>>(IA, *DFG)
552 << "\n");
553
554 NodeList UNodeList;
555 getAllRealUses(SA, UNodeList);
556
557 if (!allValidCandidates(SA, UNodeList))
558 continue;
559
560 short SizeInc = 0;
561 unsigned DefR = MI->getOperand(0).getReg();
562 InstrEvalMap InstrEvalResult;
563
564 // Analyze all uses and calculate increase in size. Perform the optimization
565 // only if there is no increase in size.
566 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
567 continue;
568 if (SizeInc > CodeGrowthLimit)
569 continue;
570
571 bool KeepTfr = false;
572
573 DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size() << "\n");
574 DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
575 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
576 NodeAddr<UseNode *> UseN = *I;
577 assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&
578 "Found a PhiRef node as a real reached use!!");
579
580 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
581 MachineInstr *UseMI = OwnerN.Addr->getCode();
582 unsigned BBNum = UseMI->getParent()->getNumber();
583 DEBUG(dbgs() << "\t\t[MI <BB#" << BBNum << ">]: " << *UseMI << "\n");
584
585 int UseMOnum = -1;
586 unsigned NumOperands = UseMI->getNumOperands();
587 for (unsigned j = 0; j < NumOperands - 1; ++j) {
588 const MachineOperand &op = UseMI->getOperand(j);
589 if (op.isReg() && op.isUse() && DefR == op.getReg())
590 UseMOnum = j;
591 }
592 assert(UseMOnum >= 0 && "Invalid reached use!");
593
594 if (InstrEvalResult[UseMI])
595 // Change UseMI if replacement is possible.
596 Changed |= xformUseMI(MI, UseMI, UseN, UseMOnum);
597 else
598 KeepTfr = true;
599 }
600 if (!KeepTfr)
601 Deleted.insert(MI);
602 }
603 return Changed;
604}
605
606void HexagonOptAddrMode::updateMap(NodeAddr<InstrNode *> IA) {
607 RegisterSet RRs;
608 for (NodeAddr<RefNode *> RA : IA.Addr->members(*DFG))
609 RRs.insert(RA.Addr->getRegRef());
610 bool Common = false;
611 for (auto &R : RDefMap) {
612 if (!RRs.count(R.first))
613 continue;
614 Common = true;
615 break;
616 }
617 if (!Common)
618 return;
619
620 for (auto &R : RDefMap) {
621 auto F = DefM.find(R.first);
622 if (F == DefM.end() || F->second.empty())
623 continue;
624 R.second[IA.Id] = F->second.top()->Id;
625 }
626}
627
628bool HexagonOptAddrMode::constructDefMap(MachineBasicBlock *B) {
629 bool Changed = false;
630 auto BA = DFG->getFunc().Addr->findBlock(B, *DFG);
631 DFG->markBlock(BA.Id, DefM);
632
633 for (NodeAddr<InstrNode *> IA : BA.Addr->members(*DFG)) {
634 updateMap(IA);
635 DFG->pushDefs(IA, DefM);
636 }
637
638 MachineDomTreeNode *N = MDT->getNode(B);
639 for (auto I : *N)
640 Changed |= constructDefMap(I->getBlock());
641
642 DFG->releaseBlock(BA.Id, DefM);
643 return Changed;
644}
645
646bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
647 bool Changed = false;
648 auto &HST = MF.getSubtarget<HexagonSubtarget>();
649 auto &MRI = MF.getRegInfo();
650 HII = HST.getInstrInfo();
651 const auto &MDF = getAnalysis<MachineDominanceFrontier>();
652 MDT = &getAnalysis<MachineDominatorTree>();
653 const auto &TRI = *MF.getSubtarget().getRegisterInfo();
654 const TargetOperandInfo TOI(*HII);
655
656 RegisterAliasInfo RAI(TRI);
657 DataFlowGraph G(MF, *HII, TRI, *MDT, MDF, RAI, TOI);
658 G.build();
659 DFG = &G;
660
661 Liveness L(MRI, *DFG);
662 L.computePhiInfo();
663 LV = &L;
664
665 constructDefMap(&DFG->getMF().front());
666
667 Deleted.clear();
668 NodeAddr<FuncNode *> FA = DFG->getFunc();
669 DEBUG(dbgs() << "==== [RefMap#]=====:\n "
670 << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");
671
672 for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))
673 Changed |= processBlock(BA);
674
675 for (auto MI : Deleted)
676 MI->eraseFromParent();
677
678 if (Changed) {
679 G.build();
680 L.computeLiveIns();
681 L.resetLiveIns();
682 L.resetKills();
683 }
684
685 return Changed;
686}
687
688//===----------------------------------------------------------------------===//
689// Public Constructor Functions
690//===----------------------------------------------------------------------===//
691
692FunctionPass *llvm::createHexagonOptAddrMode() {
693 return new HexagonOptAddrMode();
694}