blob: 148a07070d52ca113d7c22b72c00054414c20597 [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 }
Mehdi Amini117296c2016-10-01 02:56:57 +000055 StringRef getPassName() const override {
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +000056 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);
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +000082 bool hasRepForm(MachineInstr &MI, unsigned TfrDefR);
83 bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr &MI,
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +000084 const NodeList &UNodeList);
85 void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList);
86 bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList);
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +000087 short getBaseWithLongOffset(const MachineInstr &MI) const;
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +000088 void updateMap(NodeAddr<InstrNode *> IA);
89 bool constructDefMap(MachineBasicBlock *B);
90 bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
91 unsigned ImmOpNum);
92 bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum);
93 bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,
94 const MachineOperand &ImmOp, unsigned ImmOpNum);
95};
96}
97
98char HexagonOptAddrMode::ID = 0;
99
100INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "opt-amode",
101 "Optimize addressing mode", false, false)
102INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
103INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)
104INITIALIZE_PASS_END(HexagonOptAddrMode, "opt-amode", "Optimize addressing mode",
105 false, false)
106
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000107bool HexagonOptAddrMode::hasRepForm(MachineInstr &MI, unsigned TfrDefR) {
108 const MCInstrDesc &MID = MI.getDesc();
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000109
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000110 if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(MI))
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000111 return false;
112
113 if (MID.mayStore()) {
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000114 MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000115 if (StOp.isReg() && StOp.getReg() == TfrDefR)
116 return false;
117 }
118
119 if (HII->getAddrMode(MI) == HexagonII::BaseRegOffset)
120 // Tranform to Absolute plus register offset.
121 return (HII->getBaseWithLongOffset(MI) >= 0);
122 else if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset)
123 // Tranform to absolute addressing mode.
124 return (HII->getAbsoluteForm(MI) >= 0);
125
126 return false;
127}
128
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000129// Check if addasl instruction can be removed. This is possible only
130// if it's feeding to only load/store instructions with base + register
131// offset as these instruction can be tranformed to use 'absolute plus
132// shifted register offset'.
133// ex:
134// Rs = ##foo
135// Rx = addasl(Rs, Rt, #2)
136// Rd = memw(Rx + #28)
137// Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)
138
139bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN,
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000140 MachineInstr &MI,
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000141 const NodeList &UNodeList) {
142 // check offset size in addasl. if 'offset > 3' return false
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000143 const MachineOperand &OffsetOp = MI.getOperand(3);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000144 if (!OffsetOp.isImm() || OffsetOp.getImm() > 3)
145 return false;
146
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000147 unsigned OffsetReg = MI.getOperand(2).getReg();
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000148 RegisterRef OffsetRR;
149 NodeId OffsetRegRD = 0;
150 for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {
Krzysztof Parzyszek445bd122016-10-14 17:57:55 +0000151 RegisterRef RR = UA.Addr->getRegRef(*DFG);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000152 if (OffsetReg == RR.Reg) {
153 OffsetRR = RR;
154 OffsetRegRD = UA.Addr->getReachingDef();
155 }
156 }
157
158 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
159 NodeAddr<UseNode *> UA = *I;
160 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
161 if ((UA.Addr->getFlags() & NodeAttrs::PhiRef) ||
162 RDefMap[OffsetRR][IA.Id] != OffsetRegRD)
163 return false;
164
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000165 MachineInstr &UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode();
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000166 NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);
167 // Reaching Def to an offset register can't be a phi.
168 if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000169 MI.getParent() != UseMI.getParent())
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000170 return false;
171
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000172 const MCInstrDesc &UseMID = UseMI.getDesc();
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000173 if ((!UseMID.mayLoad() && !UseMID.mayStore()) ||
174 HII->getAddrMode(UseMI) != HexagonII::BaseImmOffset ||
175 getBaseWithLongOffset(UseMI) < 0)
176 return false;
177
178 // Addasl output can't be a store value.
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000179 if (UseMID.mayStore() && UseMI.getOperand(2).isReg() &&
180 UseMI.getOperand(2).getReg() == MI.getOperand(0).getReg())
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000181 return false;
182
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000183 for (auto &Mo : UseMI.operands())
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000184 if (Mo.isFI())
185 return false;
186 }
187 return true;
188}
189
190bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,
191 NodeList &UNodeList) {
192 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
193 NodeAddr<UseNode *> UN = *I;
Krzysztof Parzyszek445bd122016-10-14 17:57:55 +0000194 RegisterRef UR = UN.Addr->getRegRef(*DFG);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000195 NodeSet Visited, Defs;
196 const auto &ReachingDefs = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
197 if (ReachingDefs.size() > 1) {
Krzysztof Parzyszek4a3e2852016-05-23 17:31:30 +0000198 DEBUG({
199 dbgs() << "*** Multiple Reaching Defs found!!! ***\n";
200 for (auto DI : ReachingDefs) {
201 NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);
202 NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG);
203 dbgs() << "\t\t[Reaching Def]: "
204 << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";
205 }
206 });
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000207 return false;
208 }
209 }
210 return true;
211}
212
213void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,
214 NodeList &UNodeList) {
215 for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {
216 DEBUG(dbgs() << "\t\t[DefNode]: " << Print<NodeAddr<DefNode *>>(DA, *DFG)
217 << "\n");
Krzysztof Parzyszek7bb63ac2016-10-19 16:30:56 +0000218 RegisterRef DR = DFG->normalizeRef(DA.Addr->getRegRef(*DFG));
219
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000220 auto UseSet = LV->getAllReachedUses(DR, DA);
221
222 for (auto UI : UseSet) {
223 NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);
Krzysztof Parzyszek4a3e2852016-05-23 17:31:30 +0000224 DEBUG({
225 NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);
226 dbgs() << "\t\t\t[Reached Use]: "
227 << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";
228 });
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000229
230 if (UA.Addr->getFlags() & NodeAttrs::PhiRef) {
231 NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);
232 NodeId id = PA.Id;
233 const Liveness::RefMap &phiUse = LV->getRealUses(id);
234 DEBUG(dbgs() << "\t\t\t\tphi real Uses"
235 << Print<Liveness::RefMap>(phiUse, *DFG) << "\n");
236 if (phiUse.size() > 0) {
237 for (auto I : phiUse) {
Krzysztof Parzyszek7bb63ac2016-10-19 16:30:56 +0000238 if (DR.Reg != I.first)
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000239 continue;
240 auto phiUseSet = I.second;
241 for (auto phiUI : phiUseSet) {
Krzysztof Parzyszek7bb63ac2016-10-19 16:30:56 +0000242 NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000243 UNodeList.push_back(phiUA);
244 }
245 }
246 }
247 } else
248 UNodeList.push_back(UA);
249 }
250 }
251}
252
253bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,
254 const NodeList &UNodeList,
255 InstrEvalMap &InstrEvalResult,
256 short &SizeInc) {
257 bool KeepTfr = false;
258 bool HasRepInstr = false;
259 InstrEvalResult.clear();
260
261 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
262 bool CanBeReplaced = false;
263 NodeAddr<UseNode *> UN = *I;
264 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000265 MachineInstr &MI = *SN.Addr->getCode();
266 const MCInstrDesc &MID = MI.getDesc();
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000267 if ((MID.mayLoad() || MID.mayStore())) {
268 if (!hasRepForm(MI, tfrDefR)) {
269 KeepTfr = true;
270 continue;
271 }
272 SizeInc++;
273 CanBeReplaced = true;
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000274 } else if (MI.getOpcode() == Hexagon::S2_addasl_rrri) {
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000275 NodeList AddaslUseList;
276
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000277 DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI << "\n");
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000278 getAllRealUses(SN, AddaslUseList);
279 // Process phi nodes.
280 if (allValidCandidates(SN, AddaslUseList) &&
281 canRemoveAddasl(SN, MI, AddaslUseList)) {
282 SizeInc += AddaslUseList.size();
283 SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed.
284 CanBeReplaced = true;
285 } else
286 SizeInc++;
287 } else
288 // Currently, only load/store and addasl are handled.
289 // Some other instructions to consider -
290 // A2_add -> A2_addi
291 // M4_mpyrr_addr -> M4_mpyrr_addi
292 KeepTfr = true;
293
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000294 InstrEvalResult[&MI] = CanBeReplaced;
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000295 HasRepInstr |= CanBeReplaced;
296 }
297
298 // Reduce total size by 2 if original tfr can be deleted.
299 if (!KeepTfr)
300 SizeInc -= 2;
301
302 return HasRepInstr;
303}
304
305bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,
306 unsigned ImmOpNum) {
307 bool Changed = false;
308 MachineBasicBlock *BB = OldMI->getParent();
309 auto UsePos = MachineBasicBlock::iterator(OldMI);
310 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
311 ++InsertPt;
312 unsigned OpStart;
313 unsigned OpEnd = OldMI->getNumOperands();
314 MachineInstrBuilder MIB;
315
316 if (ImmOpNum == 1) {
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000317 if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) {
318 short NewOpCode = HII->getBaseWithLongOffset(*OldMI);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000319 assert(NewOpCode >= 0 && "Invalid New opcode\n");
320 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
321 MIB.addOperand(OldMI->getOperand(0));
322 MIB.addOperand(OldMI->getOperand(2));
323 MIB.addOperand(OldMI->getOperand(3));
324 MIB.addOperand(ImmOp);
325 OpStart = 4;
326 Changed = true;
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000327 } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset) {
328 short NewOpCode = HII->getAbsoluteForm(*OldMI);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000329 assert(NewOpCode >= 0 && "Invalid New opcode\n");
330 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))
331 .addOperand(OldMI->getOperand(0));
332 const GlobalValue *GV = ImmOp.getGlobal();
333 int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm();
334
335 MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
336 OpStart = 3;
337 Changed = true;
338 } else
339 Changed = false;
340
341 DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
342 DEBUG(dbgs() << "[TO]: " << MIB << "\n");
343 } else if (ImmOpNum == 2 && OldMI->getOperand(3).getImm() == 0) {
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000344 short NewOpCode = HII->xformRegToImmOffset(*OldMI);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000345 assert(NewOpCode >= 0 && "Invalid New opcode\n");
346 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
347 MIB.addOperand(OldMI->getOperand(0));
348 MIB.addOperand(OldMI->getOperand(1));
349 MIB.addOperand(ImmOp);
350 OpStart = 4;
351 Changed = true;
352 DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
353 DEBUG(dbgs() << "[TO]: " << MIB << "\n");
354 }
355
356 if (Changed)
357 for (unsigned i = OpStart; i < OpEnd; ++i)
358 MIB.addOperand(OldMI->getOperand(i));
359
360 return Changed;
361}
362
363bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
364 unsigned ImmOpNum) {
365 bool Changed = false;
366 unsigned OpStart;
367 unsigned OpEnd = OldMI->getNumOperands();
368 MachineBasicBlock *BB = OldMI->getParent();
369 auto UsePos = MachineBasicBlock::iterator(OldMI);
370 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
371 ++InsertPt;
372 MachineInstrBuilder MIB;
373 if (ImmOpNum == 0) {
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000374 if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) {
375 short NewOpCode = HII->getBaseWithLongOffset(*OldMI);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000376 assert(NewOpCode >= 0 && "Invalid New opcode\n");
377 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
378 MIB.addOperand(OldMI->getOperand(1));
379 MIB.addOperand(OldMI->getOperand(2));
380 MIB.addOperand(ImmOp);
381 MIB.addOperand(OldMI->getOperand(3));
382 OpStart = 4;
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000383 } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset) {
384 short NewOpCode = HII->getAbsoluteForm(*OldMI);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000385 assert(NewOpCode >= 0 && "Invalid New opcode\n");
386 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
387 const GlobalValue *GV = ImmOp.getGlobal();
388 int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm();
389 MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
390 MIB.addOperand(OldMI->getOperand(2));
391 OpStart = 3;
392 }
393 Changed = true;
394 DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
395 DEBUG(dbgs() << "[TO]: " << MIB << "\n");
396 } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) {
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000397 short NewOpCode = HII->xformRegToImmOffset(*OldMI);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000398 assert(NewOpCode >= 0 && "Invalid New opcode\n");
399 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
400 MIB.addOperand(OldMI->getOperand(0));
401 MIB.addOperand(ImmOp);
402 MIB.addOperand(OldMI->getOperand(1));
403 OpStart = 2;
404 Changed = true;
405 DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
406 DEBUG(dbgs() << "[TO]: " << MIB << "\n");
407 }
408 if (Changed)
409 for (unsigned i = OpStart; i < OpEnd; ++i)
410 MIB.addOperand(OldMI->getOperand(i));
411
412 return Changed;
413}
414
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000415short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr &MI) const {
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000416 if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) {
417 short TempOpCode = HII->getBaseWithRegOffset(MI);
418 return HII->getBaseWithLongOffset(TempOpCode);
419 } else
420 return HII->getBaseWithLongOffset(MI);
421}
422
423bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,
424 MachineInstr *AddAslMI,
425 const MachineOperand &ImmOp,
426 unsigned ImmOpNum) {
427 NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);
428
429 DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");
430
431 NodeList UNodeList;
432 getAllRealUses(SA, UNodeList);
433
434 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
435 NodeAddr<UseNode *> UseUN = *I;
436 assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) &&
437 "Can't transform this 'AddAsl' instruction!");
438
439 NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);
440 DEBUG(dbgs() << "[InstrNode]: " << Print<NodeAddr<InstrNode *>>(UseIA, *DFG)
441 << "\n");
442 MachineInstr *UseMI = UseIA.Addr->getCode();
443 DEBUG(dbgs() << "[MI <BB#" << UseMI->getParent()->getNumber()
444 << ">]: " << *UseMI << "\n");
445 const MCInstrDesc &UseMID = UseMI->getDesc();
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000446 assert(HII->getAddrMode(*UseMI) == HexagonII::BaseImmOffset);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000447
448 auto UsePos = MachineBasicBlock::iterator(UseMI);
449 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000450 short NewOpCode = getBaseWithLongOffset(*UseMI);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000451 assert(NewOpCode >= 0 && "Invalid New opcode\n");
452
453 unsigned OpStart;
454 unsigned OpEnd = UseMI->getNumOperands();
455
456 MachineBasicBlock *BB = UseMI->getParent();
457 MachineInstrBuilder MIB =
458 BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode));
459 // change mem(Rs + # ) -> mem(Rt << # + ##)
460 if (UseMID.mayLoad()) {
461 MIB.addOperand(UseMI->getOperand(0));
462 MIB.addOperand(AddAslMI->getOperand(2));
463 MIB.addOperand(AddAslMI->getOperand(3));
464 const GlobalValue *GV = ImmOp.getGlobal();
465 MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm(),
466 ImmOp.getTargetFlags());
467 OpStart = 3;
468 } else if (UseMID.mayStore()) {
469 MIB.addOperand(AddAslMI->getOperand(2));
470 MIB.addOperand(AddAslMI->getOperand(3));
471 const GlobalValue *GV = ImmOp.getGlobal();
472 MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm(),
473 ImmOp.getTargetFlags());
474 MIB.addOperand(UseMI->getOperand(2));
475 OpStart = 3;
476 } else
477 llvm_unreachable("Unhandled instruction");
478
479 for (unsigned i = OpStart; i < OpEnd; ++i)
480 MIB.addOperand(UseMI->getOperand(i));
481
482 Deleted.insert(UseMI);
483 }
484
485 return true;
486}
487
488bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
489 NodeAddr<UseNode *> UseN,
490 unsigned UseMOnum) {
491 const MachineOperand ImmOp = TfrMI->getOperand(1);
492 const MCInstrDesc &MID = UseMI->getDesc();
493 unsigned Changed = false;
494 if (MID.mayLoad())
495 Changed = changeLoad(UseMI, ImmOp, UseMOnum);
496 else if (MID.mayStore())
497 Changed = changeStore(UseMI, ImmOp, UseMOnum);
498 else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri)
499 Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
500
501 if (Changed)
502 Deleted.insert(UseMI);
503
504 return Changed;
505}
506
507bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {
508 bool Changed = false;
509
510 for (auto IA : BA.Addr->members(*DFG)) {
511 if (!DFG->IsCode<NodeAttrs::Stmt>(IA))
512 continue;
513
514 NodeAddr<StmtNode *> SA = IA;
515 MachineInstr *MI = SA.Addr->getCode();
516 if (MI->getOpcode() != Hexagon::A2_tfrsi ||
517 !MI->getOperand(1).isGlobal())
518 continue;
519
520 DEBUG(dbgs() << "[Analyzing A2_tfrsi]: " << *MI << "\n");
521 DEBUG(dbgs() << "\t[InstrNode]: " << Print<NodeAddr<InstrNode *>>(IA, *DFG)
522 << "\n");
523
524 NodeList UNodeList;
525 getAllRealUses(SA, UNodeList);
526
527 if (!allValidCandidates(SA, UNodeList))
528 continue;
529
530 short SizeInc = 0;
531 unsigned DefR = MI->getOperand(0).getReg();
532 InstrEvalMap InstrEvalResult;
533
534 // Analyze all uses and calculate increase in size. Perform the optimization
535 // only if there is no increase in size.
536 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
537 continue;
538 if (SizeInc > CodeGrowthLimit)
539 continue;
540
541 bool KeepTfr = false;
542
543 DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size() << "\n");
544 DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
545 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
546 NodeAddr<UseNode *> UseN = *I;
547 assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&
548 "Found a PhiRef node as a real reached use!!");
549
550 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
551 MachineInstr *UseMI = OwnerN.Addr->getCode();
Krzysztof Parzyszek4a3e2852016-05-23 17:31:30 +0000552 DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber()
553 << ">]: " << *UseMI << "\n");
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000554
555 int UseMOnum = -1;
556 unsigned NumOperands = UseMI->getNumOperands();
557 for (unsigned j = 0; j < NumOperands - 1; ++j) {
558 const MachineOperand &op = UseMI->getOperand(j);
559 if (op.isReg() && op.isUse() && DefR == op.getReg())
560 UseMOnum = j;
561 }
562 assert(UseMOnum >= 0 && "Invalid reached use!");
563
564 if (InstrEvalResult[UseMI])
565 // Change UseMI if replacement is possible.
566 Changed |= xformUseMI(MI, UseMI, UseN, UseMOnum);
567 else
568 KeepTfr = true;
569 }
570 if (!KeepTfr)
571 Deleted.insert(MI);
572 }
573 return Changed;
574}
575
576void HexagonOptAddrMode::updateMap(NodeAddr<InstrNode *> IA) {
577 RegisterSet RRs;
578 for (NodeAddr<RefNode *> RA : IA.Addr->members(*DFG))
Krzysztof Parzyszek445bd122016-10-14 17:57:55 +0000579 RRs.insert(RA.Addr->getRegRef(*DFG));
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000580 bool Common = false;
581 for (auto &R : RDefMap) {
582 if (!RRs.count(R.first))
583 continue;
584 Common = true;
585 break;
586 }
587 if (!Common)
588 return;
589
590 for (auto &R : RDefMap) {
Krzysztof Parzyszeka77fe4e2016-10-03 17:14:48 +0000591 auto F = DefM.find(R.first.Reg);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000592 if (F == DefM.end() || F->second.empty())
593 continue;
594 R.second[IA.Id] = F->second.top()->Id;
595 }
596}
597
598bool HexagonOptAddrMode::constructDefMap(MachineBasicBlock *B) {
599 bool Changed = false;
600 auto BA = DFG->getFunc().Addr->findBlock(B, *DFG);
601 DFG->markBlock(BA.Id, DefM);
602
603 for (NodeAddr<InstrNode *> IA : BA.Addr->members(*DFG)) {
604 updateMap(IA);
605 DFG->pushDefs(IA, DefM);
606 }
607
608 MachineDomTreeNode *N = MDT->getNode(B);
609 for (auto I : *N)
610 Changed |= constructDefMap(I->getBlock());
611
612 DFG->releaseBlock(BA.Id, DefM);
613 return Changed;
614}
615
616bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
617 bool Changed = false;
618 auto &HST = MF.getSubtarget<HexagonSubtarget>();
619 auto &MRI = MF.getRegInfo();
620 HII = HST.getInstrInfo();
621 const auto &MDF = getAnalysis<MachineDominanceFrontier>();
622 MDT = &getAnalysis<MachineDominatorTree>();
623 const auto &TRI = *MF.getSubtarget().getRegisterInfo();
624 const TargetOperandInfo TOI(*HII);
625
Krzysztof Parzyszeka77fe4e2016-10-03 17:14:48 +0000626 DataFlowGraph G(MF, *HII, TRI, *MDT, MDF, TOI);
Krzysztof Parzyszekf5cbac92016-04-29 15:49:13 +0000627 G.build();
628 DFG = &G;
629
630 Liveness L(MRI, *DFG);
631 L.computePhiInfo();
632 LV = &L;
633
634 constructDefMap(&DFG->getMF().front());
635
636 Deleted.clear();
637 NodeAddr<FuncNode *> FA = DFG->getFunc();
638 DEBUG(dbgs() << "==== [RefMap#]=====:\n "
639 << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");
640
641 for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))
642 Changed |= processBlock(BA);
643
644 for (auto MI : Deleted)
645 MI->eraseFromParent();
646
647 if (Changed) {
648 G.build();
649 L.computeLiveIns();
650 L.resetLiveIns();
651 L.resetKills();
652 }
653
654 return Changed;
655}
656
657//===----------------------------------------------------------------------===//
658// Public Constructor Functions
659//===----------------------------------------------------------------------===//
660
661FunctionPass *llvm::createHexagonOptAddrMode() {
662 return new HexagonOptAddrMode();
663}