LLVM 22.0.0git
HexagonOptAddrMode.cpp
Go to the documentation of this file.
1//===- HexagonOptAddrMode.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// This implements a Hexagon-specific pass to optimize addressing mode for
9// load/store instructions.
10//===----------------------------------------------------------------------===//
11
12#include "Hexagon.h"
13#include "HexagonInstrInfo.h"
14#include "HexagonSubtarget.h"
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/DenseSet.h"
18#include "llvm/ADT/StringRef.h"
33#include "llvm/MC/MCInstrDesc.h"
34#include "llvm/Pass.h"
36#include "llvm/Support/Debug.h"
39#include <cassert>
40#include <cstdint>
41
42#define DEBUG_TYPE "opt-addr-mode"
43
44using namespace llvm;
45using namespace rdf;
46
47static cl::opt<int> CodeGrowthLimit("hexagon-amode-growth-limit",
48 cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode "
49 "optimization"));
50
52
53namespace {
54
55class HexagonOptAddrMode : public MachineFunctionPass {
56public:
57 static char ID;
58
59 HexagonOptAddrMode() : MachineFunctionPass(ID) {}
60
61 StringRef getPassName() const override {
62 return "Optimize addressing mode of load/store";
63 }
64
65 void getAnalysisUsage(AnalysisUsage &AU) const override {
67 AU.addRequired<MachineDominatorTreeWrapperPass>();
68 AU.addRequired<MachineDominanceFrontier>();
69 AU.setPreservesAll();
70 }
71
72 bool runOnMachineFunction(MachineFunction &MF) override;
73
74private:
75 using MISetType = DenseSet<MachineInstr *>;
76 using InstrEvalMap = DenseMap<MachineInstr *, bool>;
77 DenseSet<MachineInstr *> ProcessedAddiInsts;
78
79 MachineRegisterInfo *MRI = nullptr;
80 const TargetRegisterInfo *TRI = nullptr;
81 const HexagonInstrInfo *HII = nullptr;
82 const HexagonRegisterInfo *HRI = nullptr;
83 MachineDominatorTree *MDT = nullptr;
84 DataFlowGraph *DFG = nullptr;
86 Liveness *LV = nullptr;
87 MISetType Deleted;
88
89 bool processBlock(NodeAddr<BlockNode *> BA);
90 bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
91 NodeAddr<UseNode *> UseN, unsigned UseMOnum);
92 bool processAddBases(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI);
93 bool usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN, int64_t NewOffset);
94 bool findFirstReachedInst(
95 MachineInstr *AddMI,
96 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>>
97 &AddiList,
98 NodeAddr<StmtNode *> &UseSN);
99 bool updateAddBases(MachineInstr *CurrentMI, MachineInstr *FirstReachedMI,
100 int64_t NewOffset);
101 bool processAddUses(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI,
102 const NodeList &UNodeList);
103 bool updateAddUses(MachineInstr *AddMI, MachineInstr *UseMI);
104 bool analyzeUses(unsigned DefR, const NodeList &UNodeList,
105 InstrEvalMap &InstrEvalResult, short &SizeInc);
106 bool hasRepForm(MachineInstr &MI, unsigned TfrDefR);
107 bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr &MI,
108 const NodeList &UNodeList);
109 bool isSafeToExtLR(NodeAddr<StmtNode *> SN, MachineInstr *MI,
110 unsigned LRExtReg, const NodeList &UNodeList);
111 void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList);
112 bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList);
113 short getBaseWithLongOffset(const MachineInstr &MI) const;
114 bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
115 unsigned ImmOpNum);
116 bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum);
117 bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,
118 const MachineOperand &ImmOp, unsigned ImmOpNum);
119 bool isValidOffset(MachineInstr *MI, int Offset);
120 unsigned getBaseOpPosition(MachineInstr *MI);
121 unsigned getOffsetOpPosition(MachineInstr *MI);
122};
123
124} // end anonymous namespace
125
126char HexagonOptAddrMode::ID = 0;
127
128INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "amode-opt",
129 "Optimize addressing mode", false, false)
132INITIALIZE_PASS_END(HexagonOptAddrMode, "amode-opt", "Optimize addressing mode",
134
135bool HexagonOptAddrMode::hasRepForm(MachineInstr &MI, unsigned TfrDefR) {
136 const MCInstrDesc &MID = MI.getDesc();
137
138 if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(MI))
139 return false;
140
141 if (MID.mayStore()) {
142 MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1);
143 if (StOp.isReg() && StOp.getReg() == TfrDefR)
144 return false;
145 }
146
147 if (HII->getAddrMode(MI) == HexagonII::BaseRegOffset)
148 // Transform to Absolute plus register offset.
149 return (HII->changeAddrMode_rr_ur(MI) >= 0);
150 else if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset)
151 // Transform to absolute addressing mode.
152 return (HII->changeAddrMode_io_abs(MI) >= 0);
153
154 return false;
155}
156
157// Check if addasl instruction can be removed. This is possible only
158// if it's feeding to only load/store instructions with base + register
159// offset as these instruction can be transformed to use 'absolute plus
160// shifted register offset'.
161// ex:
162// Rs = ##foo
163// Rx = addasl(Rs, Rt, #2)
164// Rd = memw(Rx + #28)
165// Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)
166
167bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN,
169 const NodeList &UNodeList) {
170 // check offset size in addasl. if 'offset > 3' return false
171 const MachineOperand &OffsetOp = MI.getOperand(3);
172 if (!OffsetOp.isImm() || OffsetOp.getImm() > 3)
173 return false;
174
175 Register OffsetReg = MI.getOperand(2).getReg();
176 RegisterRef OffsetRR;
177 NodeId OffsetRegRD = 0;
178 for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {
179 RegisterRef RR = UA.Addr->getRegRef(*DFG);
180 if (OffsetReg == RR.Reg) {
181 OffsetRR = RR;
182 OffsetRegRD = UA.Addr->getReachingDef();
183 }
184 }
185
186 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
187 NodeAddr<UseNode *> UA = *I;
188 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
189 if (UA.Addr->getFlags() & NodeAttrs::PhiRef)
190 return false;
191 NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(OffsetRR, IA);
192 if ((DFG->IsDef(AA) && AA.Id != OffsetRegRD) ||
193 AA.Addr->getReachingDef() != OffsetRegRD)
194 return false;
195
196 MachineInstr &UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode();
197 NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);
198 // Reaching Def to an offset register can't be a phi.
199 if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&
200 MI.getParent() != UseMI.getParent())
201 return false;
202
203 const MCInstrDesc &UseMID = UseMI.getDesc();
204 if ((!UseMID.mayLoad() && !UseMID.mayStore()) ||
206 getBaseWithLongOffset(UseMI) < 0)
207 return false;
208
209 // Addasl output can't be a store value.
210 if (UseMID.mayStore() && UseMI.getOperand(2).isReg() &&
211 UseMI.getOperand(2).getReg() == MI.getOperand(0).getReg())
212 return false;
213
214 for (auto &Mo : UseMI.operands())
215 // Is it a frame index?
216 if (Mo.isFI())
217 return false;
218 // Is the OffsetReg definition actually reaches UseMI?
219 if (!UseMI.getParent()->isLiveIn(OffsetReg) &&
220 MI.getParent() != UseMI.getParent()) {
221 LLVM_DEBUG(dbgs() << " The offset reg " << printReg(OffsetReg, TRI)
222 << " is NOT live in to MBB "
223 << UseMI.getParent()->getName() << "\n");
224 return false;
225 }
226 }
227 return true;
228}
229
230bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,
231 NodeList &UNodeList) {
232 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
233 NodeAddr<UseNode *> UN = *I;
234 RegisterRef UR = UN.Addr->getRegRef(*DFG);
235 NodeSet Visited, Defs;
236 const auto &P = LV->getAllReachingDefsRec(UR, UN, Visited, Defs);
237 if (!P.second) {
238 LLVM_DEBUG({
239 dbgs() << "*** Unable to collect all reaching defs for use ***\n"
240 << PrintNode<UseNode*>(UN, *DFG) << '\n'
241 << "The program's complexity may exceed the limits.\n";
242 });
243 return false;
244 }
245 const auto &ReachingDefs = P.first;
246 if (ReachingDefs.size() > 1) {
247 LLVM_DEBUG({
248 dbgs() << "*** Multiple Reaching Defs found!!! ***\n";
249 for (auto DI : ReachingDefs) {
250 NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);
251 NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG);
252 dbgs() << "\t\t[Reaching Def]: "
253 << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";
254 }
255 });
256 return false;
257 }
258 }
259 return true;
260}
261
262void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,
263 NodeList &UNodeList) {
264 for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {
265 LLVM_DEBUG(dbgs() << "\t\t[DefNode]: "
266 << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n");
267 RegisterRef DR = DA.Addr->getRegRef(*DFG);
268
269 auto UseSet = LV->getAllReachedUses(DR, DA);
270
271 for (auto UI : UseSet) {
272 NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);
273 LLVM_DEBUG({
274 NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);
275 dbgs() << "\t\t\t[Reached Use]: "
276 << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";
277 });
278
279 if (UA.Addr->getFlags() & NodeAttrs::PhiRef) {
280 NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);
281 NodeId id = PA.Id;
282 const Liveness::RefMap &phiUse = LV->getRealUses(id);
283 LLVM_DEBUG(dbgs() << "\t\t\t\tphi real Uses"
284 << Print<Liveness::RefMap>(phiUse, *DFG) << "\n");
285 if (!phiUse.empty()) {
286 for (auto I : phiUse) {
287 if (!DFG->getPRI().alias(RegisterRef(I.first), DR))
288 continue;
289 auto phiUseSet = I.second;
290 for (auto phiUI : phiUseSet) {
291 NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first);
292 UNodeList.push_back(phiUA);
293 }
294 }
295 }
296 } else
297 UNodeList.push_back(UA);
298 }
299 }
300}
301
302bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN,
303 MachineInstr *MI, unsigned LRExtReg,
304 const NodeList &UNodeList) {
305 RegisterRef LRExtRR;
306 NodeId LRExtRegRD = 0;
307 // Iterate through all the UseNodes in SN and find the reaching def
308 // for the LRExtReg.
309 for (NodeAddr<UseNode *> UA : SN.Addr->members_if(DFG->IsUse, *DFG)) {
310 RegisterRef RR = UA.Addr->getRegRef(*DFG);
311 if (LRExtReg == RR.Reg) {
312 LRExtRR = RR;
313 LRExtRegRD = UA.Addr->getReachingDef();
314 }
315 }
316
317 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
318 NodeAddr<UseNode *> UA = *I;
319 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);
320 // The reaching def of LRExtRR at load/store node should be same as the
321 // one reaching at the SN.
322 if (UA.Addr->getFlags() & NodeAttrs::PhiRef)
323 return false;
324 NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(LRExtRR, IA);
325 if ((DFG->IsDef(AA) && AA.Id != LRExtRegRD) ||
326 AA.Addr->getReachingDef() != LRExtRegRD) {
328 dbgs() << "isSafeToExtLR: Returning false; another reaching def\n");
329 return false;
330 }
331
332 // If the register is undefined (for example if it's a reserved register),
333 // it may still be possible to extend the range, but it's safer to be
334 // conservative and just punt.
335 if (LRExtRegRD == 0)
336 return false;
337
338 MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode();
339 NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);
340 // Reaching Def to LRExtReg can't be a phi.
341 if ((LRExtRegDN.Addr->getFlags() & NodeAttrs::PhiRef) &&
342 MI->getParent() != UseMI->getParent())
343 return false;
344 // Is the OffsetReg definition actually reaches UseMI?
345 if (!UseMI->getParent()->isLiveIn(LRExtReg) &&
346 MI->getParent() != UseMI->getParent()) {
347 LLVM_DEBUG(dbgs() << " The LRExtReg reg " << printReg(LRExtReg, TRI)
348 << " is NOT live in to MBB "
349 << UseMI->getParent()->getName() << "\n");
350 return false;
351 }
352 }
353 return true;
354}
355
356bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) {
357 if (HII->isHVXVec(*MI)) {
358 // only HVX vgather instructions handled
359 // TODO: extend the pass to other vector load/store operations
360 switch (MI->getOpcode()) {
361 case Hexagon::V6_vgathermh_pseudo:
362 case Hexagon::V6_vgathermw_pseudo:
363 case Hexagon::V6_vgathermhw_pseudo:
364 case Hexagon::V6_vgathermhq_pseudo:
365 case Hexagon::V6_vgathermwq_pseudo:
366 case Hexagon::V6_vgathermhwq_pseudo:
367 return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);
368 default:
370 // The immediates are mentioned in multiples of vector counts
371 unsigned AlignMask = HII->getMemAccessSize(*MI) - 1;
372 if ((AlignMask & Offset) == 0)
373 return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);
374 }
375 return false;
376 }
377 }
378
380 return false;
381
382 unsigned AlignMask = 0;
383 switch (HII->getMemAccessSize(*MI)) {
384 case HexagonII::MemAccessSize::DoubleWordAccess:
385 AlignMask = 0x7;
386 break;
387 case HexagonII::MemAccessSize::WordAccess:
388 AlignMask = 0x3;
389 break;
390 case HexagonII::MemAccessSize::HalfWordAccess:
391 AlignMask = 0x1;
392 break;
393 case HexagonII::MemAccessSize::ByteAccess:
394 AlignMask = 0x0;
395 break;
396 default:
397 return false;
398 }
399
400 if ((AlignMask & Offset) != 0)
401 return false;
402 return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);
403}
404
405unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *MI) {
406 const MCInstrDesc &MID = MI->getDesc();
407 switch (MI->getOpcode()) {
408 // vgather pseudos are mayLoad and mayStore
409 // hence need to explicitly specify Base and
410 // Offset operand positions
411 case Hexagon::V6_vgathermh_pseudo:
412 case Hexagon::V6_vgathermw_pseudo:
413 case Hexagon::V6_vgathermhw_pseudo:
414 case Hexagon::V6_vgathermhq_pseudo:
415 case Hexagon::V6_vgathermwq_pseudo:
416 case Hexagon::V6_vgathermhwq_pseudo:
417 return 0;
418 default:
419 return MID.mayLoad() ? 1 : 0;
420 }
421}
422
423unsigned HexagonOptAddrMode::getOffsetOpPosition(MachineInstr *MI) {
424 assert(
426 "Looking for an offset in non-BaseImmOffset addressing mode instruction");
427
428 const MCInstrDesc &MID = MI->getDesc();
429 switch (MI->getOpcode()) {
430 // vgather pseudos are mayLoad and mayStore
431 // hence need to explicitly specify Base and
432 // Offset operand positions
433 case Hexagon::V6_vgathermh_pseudo:
434 case Hexagon::V6_vgathermw_pseudo:
435 case Hexagon::V6_vgathermhw_pseudo:
436 case Hexagon::V6_vgathermhq_pseudo:
437 case Hexagon::V6_vgathermwq_pseudo:
438 case Hexagon::V6_vgathermhwq_pseudo:
439 return 1;
440 default:
441 return MID.mayLoad() ? 2 : 1;
442 }
443}
444
445bool HexagonOptAddrMode::usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN,
446 int64_t NewOffset) {
447 NodeList LoadStoreUseList;
448
449 getAllRealUses(CurrentInstSN, LoadStoreUseList);
450 bool FoundLoadStoreUse = false;
451 for (NodeAddr<UseNode *> UN : LoadStoreUseList) {
452 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
453 MachineInstr *LoadStoreMI = SN.Addr->getCode();
454 const MCInstrDesc &MID = LoadStoreMI->getDesc();
455 if ((MID.mayLoad() || MID.mayStore()) &&
456 isValidOffset(LoadStoreMI, NewOffset)) {
457 FoundLoadStoreUse = true;
458 break;
459 }
460 }
461 return FoundLoadStoreUse;
462}
463
464bool HexagonOptAddrMode::findFirstReachedInst(
465 MachineInstr *AddMI,
466 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> &AddiList,
467 NodeAddr<StmtNode *> &UseSN) {
468 // Find the very first Addi instruction in the current basic block among the
469 // AddiList This is the Addi that should be preserved so that we do not need
470 // to handle the complexity of moving instructions
471 //
472 // TODO: find Addi instructions across basic blocks
473 //
474 // TODO: Try to remove this and add a solution that optimizes the number of
475 // Addi instructions that can be modified.
476 // This change requires choosing the Addi with the median offset value, but
477 // would also require moving that instruction above the others. Since this
478 // pass runs after register allocation, there might be multiple cases that
479 // need to be handled if we move instructions around
480 MachineBasicBlock *CurrentMBB = AddMI->getParent();
481 for (auto &InstIter : *CurrentMBB) {
482 // If the instruction is an Addi and is in the AddiList
483 if (InstIter.getOpcode() == Hexagon::A2_addi) {
484 auto Iter = llvm::find_if(AddiList, [&InstIter](const auto &SUPair) {
485 return SUPair.first.Addr->getCode() == &InstIter;
486 });
487 if (Iter != AddiList.end()) {
488 UseSN = Iter->first;
489 return true;
490 }
491 }
492 }
493 return false;
494}
495
496// This function tries to modify the immediate value in Hexagon::Addi
497// instructions, so that the immediates could then be moved into a load/store
498// instruction with offset and the add removed completely when we call
499// processAddUses
500//
501// For Example, If we have the below sequence of instructions:
502//
503// r1 = add(r2,#1024)
504// ...
505// r3 = add(r2,#1152)
506// ...
507// r4 = add(r2,#1280)
508//
509// Where the register r2 has the same reaching definition, They get modified to
510// the below sequence:
511//
512// r1 = add(r2,#1024)
513// ...
514// r3 = add(r1,#128)
515// ...
516// r4 = add(r1,#256)
517//
518// The below change helps the processAddUses method to later move the
519// immediates #128 and #256 into a load/store instruction that can take an
520// offset, like the Vd = mem(Rt+#s4)
521bool HexagonOptAddrMode::processAddBases(NodeAddr<StmtNode *> AddSN,
522 MachineInstr *AddMI) {
523
524 bool Changed = false;
525
526 LLVM_DEBUG(dbgs() << "\n\t\t[Processing Addi]: " << *AddMI << "\n");
527
528 auto Processed =
529 [](const MachineInstr *MI,
530 const DenseSet<MachineInstr *> &ProcessedAddiInsts) -> bool {
531 // If we've already processed this Addi, just return
532 if (ProcessedAddiInsts.contains(MI)) {
533 LLVM_DEBUG(dbgs() << "\t\t\tAddi already found in ProcessedAddiInsts: "
534 << *MI << "\n\t\t\tSkipping...");
535 return true;
536 }
537 return false;
538 };
539
540 if (Processed(AddMI, ProcessedAddiInsts))
541 return Changed;
542 ProcessedAddiInsts.insert(AddMI);
543
544 // Get the base register that would be shared by other Addi Instructions
545 Register BaseReg = AddMI->getOperand(1).getReg();
546
547 // Store a list of all Addi instructions that share the above common base
548 // register
549 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> AddiList;
550
551 NodeId UAReachingDefID;
552 // Find the UseNode that contains the base register and it's reachingDef
553 for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {
554 RegisterRef URR = UA.Addr->getRegRef(*DFG);
555 if (BaseReg != URR.Reg)
556 continue;
557
558 UAReachingDefID = UA.Addr->getReachingDef();
559 NodeAddr<DefNode *> UADef = DFG->addr<DefNode *>(UAReachingDefID);
560 if (!UAReachingDefID || UADef.Addr->getFlags() & NodeAttrs::PhiRef) {
561 LLVM_DEBUG(dbgs() << "\t\t\t Could not find reachingDef. Skipping...\n");
562 return false;
563 }
564 }
565
566 NodeAddr<DefNode *> UAReachingDef = DFG->addr<DefNode *>(UAReachingDefID);
567 NodeAddr<StmtNode *> ReachingDefStmt = UAReachingDef.Addr->getOwner(*DFG);
568
569 // If the reaching definition is a predicated instruction, this might not be
570 // the only definition of our base register, so return immediately.
571 MachineInstr *ReachingDefInstr = ReachingDefStmt.Addr->getCode();
572 if (HII->isPredicated(*ReachingDefInstr))
573 return false;
574
575 NodeList AddiUseList;
576
577 // Find all Addi instructions that share the same base register and add them
578 // to the AddiList
579 getAllRealUses(ReachingDefStmt, AddiUseList);
580 for (NodeAddr<UseNode *> UN : AddiUseList) {
581 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
582 MachineInstr *MI = SN.Addr->getCode();
583
584 // Only add instructions if it's an Addi and it's not already processed.
585 if (MI->getOpcode() == Hexagon::A2_addi &&
586 !(MI != AddMI && Processed(MI, ProcessedAddiInsts))) {
587 AddiList.push_back({SN, UN});
588
589 // This ensures that we process each instruction only once
590 ProcessedAddiInsts.insert(MI);
591 }
592 }
593
594 // If there's only one Addi instruction, nothing to do here
595 if (AddiList.size() <= 1)
596 return Changed;
597
598 NodeAddr<StmtNode *> FirstReachedUseSN;
599 // Find the first reached use of Addi instruction from the list
600 if (!findFirstReachedInst(AddMI, AddiList, FirstReachedUseSN))
601 return Changed;
602
603 // If we reach this point we know that the StmtNode FirstReachedUseSN is for
604 // an Addi instruction. So, we're guaranteed to have just one DefNode, and
605 // hence we can access the front() directly without checks
606 NodeAddr<DefNode *> FirstReachedUseDN =
607 FirstReachedUseSN.Addr->members_if(DFG->IsDef, *DFG).front();
608
609 MachineInstr *FirstReachedMI = FirstReachedUseSN.Addr->getCode();
610 const MachineOperand FirstReachedMIImmOp = FirstReachedMI->getOperand(2);
611 if (!FirstReachedMIImmOp.isImm())
612 return false;
613
614 for (auto &I : AddiList) {
615 NodeAddr<StmtNode *> CurrentInstSN = I.first;
616 NodeAddr<UseNode *> CurrentInstUN = I.second;
617
618 MachineInstr *CurrentMI = CurrentInstSN.Addr->getCode();
619 MachineOperand &CurrentMIImmOp = CurrentMI->getOperand(2);
620
621 int64_t NewOffset;
622
623 // Even though we know it's an Addi instruction, the second operand could be
624 // a global value and not an immediate
625 if (!CurrentMIImmOp.isImm())
626 continue;
627
628 NewOffset = CurrentMIImmOp.getImm() - FirstReachedMIImmOp.getImm();
629
630 // This is the first occurring Addi, so skip modifying this
631 if (CurrentMI == FirstReachedMI) {
632 continue;
633 }
634
635 if (CurrentMI->getParent() != FirstReachedMI->getParent())
636 continue;
637
638 // Modify the Addi instruction only if it could be used to modify a
639 // future load/store instruction and get removed
640 //
641 // This check is needed because, if we modify the current Addi instruction
642 // we create RAW dependence between the FirstReached Addi and the current
643 // one, which could result in extra packets. So we only do this change if
644 // we know the current Addi would get removed later
645 if (!usedInLoadStore(CurrentInstSN, NewOffset)) {
646 return false;
647 }
648
649 // Verify whether the First Addi's definition register is still live when
650 // we reach the current Addi
651 RegisterRef FirstReachedDefRR = FirstReachedUseDN.Addr->getRegRef(*DFG);
652 NodeAddr<InstrNode *> CurrentAddiIN = CurrentInstUN.Addr->getOwner(*DFG);
653 NodeAddr<RefNode *> NearestAA =
654 LV->getNearestAliasedRef(FirstReachedDefRR, CurrentAddiIN);
655 if ((DFG->IsDef(NearestAA) && NearestAA.Id != FirstReachedUseDN.Id) ||
656 (!DFG->IsDef(NearestAA) &&
657 NearestAA.Addr->getReachingDef() != FirstReachedUseDN.Id)) {
658 // Found another definition of FirstReachedDef
659 LLVM_DEBUG(dbgs() << "\t\t\tCould not modify below Addi since the first "
660 "defined Addi register was redefined\n");
661 continue;
662 }
663
664 MachineOperand CurrentMIBaseOp = CurrentMI->getOperand(1);
665 if (CurrentMIBaseOp.getReg() != FirstReachedMI->getOperand(1).getReg()) {
666 continue;
667 }
668
669 // If we reached this point, then we can modify MI to use the result of
670 // FirstReachedMI
671 Changed |= updateAddBases(CurrentMI, FirstReachedMI, NewOffset);
672
673 // Update the reachingDef of the Current AddI use after change
674 CurrentInstUN.Addr->linkToDef(CurrentInstUN.Id, FirstReachedUseDN);
675 }
676
677 return Changed;
678}
679
680bool HexagonOptAddrMode::updateAddBases(MachineInstr *CurrentMI,
681 MachineInstr *FirstReachedMI,
682 int64_t NewOffset) {
683 LLVM_DEBUG(dbgs() << "[About to modify the Addi]: " << *CurrentMI << "\n");
684 const MachineOperand FirstReachedDef = FirstReachedMI->getOperand(0);
685 Register FirstDefRegister = FirstReachedDef.getReg();
686
687 MachineOperand &CurrentMIBaseOp = CurrentMI->getOperand(1);
688 MachineOperand &CurrentMIImmOp = CurrentMI->getOperand(2);
689
690 CurrentMIBaseOp.setReg(FirstDefRegister);
691 CurrentMIBaseOp.setIsUndef(FirstReachedDef.isUndef());
692 CurrentMIBaseOp.setImplicit(FirstReachedDef.isImplicit());
693 CurrentMIImmOp.setImm(NewOffset);
694 ProcessedAddiInsts.insert(CurrentMI);
695 MRI->clearKillFlags(FirstDefRegister);
696 return true;
697}
698
699bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
700 MachineInstr *AddMI,
701 const NodeList &UNodeList) {
702
703 Register AddDefR = AddMI->getOperand(0).getReg();
704 Register BaseReg = AddMI->getOperand(1).getReg();
705 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
706 NodeAddr<UseNode *> UN = *I;
707 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
708 MachineInstr *MI = SN.Addr->getCode();
709 const MCInstrDesc &MID = MI->getDesc();
710 if ((!MID.mayLoad() && !MID.mayStore()) ||
712 return false;
713
714 MachineOperand BaseOp = MI->getOperand(getBaseOpPosition(MI));
715
716 if (!BaseOp.isReg() || BaseOp.getReg() != AddDefR)
717 return false;
718
719 MachineOperand OffsetOp = MI->getOperand(getOffsetOpPosition(MI));
720 if (!OffsetOp.isImm())
721 return false;
722
723 int64_t newOffset = OffsetOp.getImm() + AddMI->getOperand(2).getImm();
724 if (!isValidOffset(MI, newOffset))
725 return false;
726
727 // Since we'll be extending the live range of Rt in the following example,
728 // make sure that is safe. another definition of Rt doesn't exist between 'add'
729 // and load/store instruction.
730 //
731 // Ex: Rx= add(Rt,#10)
732 // memw(Rx+#0) = Rs
733 // will be replaced with => memw(Rt+#10) = Rs
734 if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
735 return false;
736 }
737
738 NodeId LRExtRegRD = 0;
739 // Iterate through all the UseNodes in SN and find the reaching def
740 // for the LRExtReg.
741 for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {
742 RegisterRef RR = UA.Addr->getRegRef(*DFG);
743 if (BaseReg == RR.Reg)
744 LRExtRegRD = UA.Addr->getReachingDef();
745 }
746
747 // Update all the uses of 'add' with the appropriate base and offset
748 // values.
749 bool Changed = false;
750 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
751 NodeAddr<UseNode *> UseN = *I;
752 assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&
753 "Found a PhiRef node as a real reached use!!");
754
755 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
756 MachineInstr *UseMI = OwnerN.Addr->getCode();
757 LLVM_DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber()
758 << ">]: " << *UseMI << "\n");
759 Changed |= updateAddUses(AddMI, UseMI);
760
761 // Set the reachingDef for UseNode under consideration
762 // after updating the Add use. This local change is
763 // to avoid rebuilding of the RDF graph after update.
764 NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);
765 UseN.Addr->linkToDef(UseN.Id, LRExtRegDN);
766 }
767
768 if (Changed)
769 Deleted.insert(AddMI);
770
771 return Changed;
772}
773
774bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI,
775 MachineInstr *UseMI) {
776 const MachineOperand ImmOp = AddMI->getOperand(2);
777 const MachineOperand AddRegOp = AddMI->getOperand(1);
778 Register NewReg = AddRegOp.getReg();
779
780 MachineOperand &BaseOp = UseMI->getOperand(getBaseOpPosition(UseMI));
781 MachineOperand &OffsetOp = UseMI->getOperand(getOffsetOpPosition(UseMI));
782 BaseOp.setReg(NewReg);
783 BaseOp.setIsUndef(AddRegOp.isUndef());
784 BaseOp.setImplicit(AddRegOp.isImplicit());
785 OffsetOp.setImm(ImmOp.getImm() + OffsetOp.getImm());
786 MRI->clearKillFlags(NewReg);
787
788 return true;
789}
790
791bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,
792 const NodeList &UNodeList,
793 InstrEvalMap &InstrEvalResult,
794 short &SizeInc) {
795 bool KeepTfr = false;
796 bool HasRepInstr = false;
797 InstrEvalResult.clear();
798
799 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
800 bool CanBeReplaced = false;
801 NodeAddr<UseNode *> UN = *I;
802 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
803 MachineInstr &MI = *SN.Addr->getCode();
804 const MCInstrDesc &MID = MI.getDesc();
805 if ((MID.mayLoad() || MID.mayStore())) {
806 if (!hasRepForm(MI, tfrDefR)) {
807 KeepTfr = true;
808 continue;
809 }
810 SizeInc++;
811 CanBeReplaced = true;
812 } else if (MI.getOpcode() == Hexagon::S2_addasl_rrri) {
813 NodeList AddaslUseList;
814
815 LLVM_DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI << "\n");
816 getAllRealUses(SN, AddaslUseList);
817 // Process phi nodes.
818 if (allValidCandidates(SN, AddaslUseList) &&
819 canRemoveAddasl(SN, MI, AddaslUseList)) {
820 SizeInc += AddaslUseList.size();
821 SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed.
822 CanBeReplaced = true;
823 } else
824 SizeInc++;
825 } else
826 // Currently, only load/store and addasl are handled.
827 // Some other instructions to consider -
828 // A2_add -> A2_addi
829 // M4_mpyrr_addr -> M4_mpyrr_addi
830 KeepTfr = true;
831
832 InstrEvalResult[&MI] = CanBeReplaced;
833 HasRepInstr |= CanBeReplaced;
834 }
835
836 // Reduce total size by 2 if original tfr can be deleted.
837 if (!KeepTfr)
838 SizeInc -= 2;
839
840 return HasRepInstr;
841}
842
843bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,
844 unsigned ImmOpNum) {
845 bool Changed = false;
846 MachineBasicBlock *BB = OldMI->getParent();
847 auto UsePos = MachineBasicBlock::iterator(OldMI);
848 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
849 ++InsertPt;
850 unsigned OpStart;
851 unsigned OpEnd = OldMI->getNumOperands();
852 MachineInstrBuilder MIB;
853
854 if (ImmOpNum == 1) {
855 if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) {
856 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);
857 assert(NewOpCode >= 0 && "Invalid New opcode\n");
858 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
859 MIB.add(OldMI->getOperand(0));
860 MIB.add(OldMI->getOperand(2));
861 MIB.add(OldMI->getOperand(3));
862 MIB.add(ImmOp);
863 OpStart = 4;
864 Changed = true;
865 } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset &&
866 OldMI->getOperand(2).isImm()) {
867 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);
868 assert(NewOpCode >= 0 && "Invalid New opcode\n");
869 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))
870 .add(OldMI->getOperand(0));
871 const GlobalValue *GV = ImmOp.getGlobal();
872 int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm();
873
874 MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
875 OpStart = 3;
876 Changed = true;
877 } else
878 Changed = false;
879
880 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
881 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n");
882 } else if (ImmOpNum == 2) {
883 if (OldMI->getOperand(3).isImm() && OldMI->getOperand(3).getImm() == 0) {
884 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);
885 assert(NewOpCode >= 0 && "Invalid New opcode\n");
886 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
887 MIB.add(OldMI->getOperand(0));
888 MIB.add(OldMI->getOperand(1));
889 MIB.add(ImmOp);
890 OpStart = 4;
891 Changed = true;
892 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
893 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n");
894 }
895 }
896
897 if (Changed)
898 for (unsigned i = OpStart; i < OpEnd; ++i)
899 MIB.add(OldMI->getOperand(i));
900
901 return Changed;
902}
903
904bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,
905 unsigned ImmOpNum) {
906 bool Changed = false;
907 unsigned OpStart = 0;
908 unsigned OpEnd = OldMI->getNumOperands();
909 MachineBasicBlock *BB = OldMI->getParent();
910 auto UsePos = MachineBasicBlock::iterator(OldMI);
911 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
912 ++InsertPt;
913 MachineInstrBuilder MIB;
914 if (ImmOpNum == 0) {
915 if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) {
916 short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI);
917 assert(NewOpCode >= 0 && "Invalid New opcode\n");
918 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
919 MIB.add(OldMI->getOperand(1));
920 MIB.add(OldMI->getOperand(2));
921 MIB.add(ImmOp);
922 MIB.add(OldMI->getOperand(3));
923 OpStart = 4;
924 Changed = true;
925 } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset) {
926 short NewOpCode = HII->changeAddrMode_io_abs(*OldMI);
927 assert(NewOpCode >= 0 && "Invalid New opcode\n");
928 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
929 const GlobalValue *GV = ImmOp.getGlobal();
930 int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm();
931 MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags());
932 MIB.add(OldMI->getOperand(2));
933 OpStart = 3;
934 Changed = true;
935 }
936 } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) {
937 short NewOpCode = HII->changeAddrMode_rr_io(*OldMI);
938 assert(NewOpCode >= 0 && "Invalid New opcode\n");
939 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));
940 MIB.add(OldMI->getOperand(0));
941 MIB.add(ImmOp);
942 OpStart = 3;
943 Changed = true;
944 }
945 if (Changed) {
946 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");
947 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n");
948
949 for (unsigned i = OpStart; i < OpEnd; ++i)
950 MIB.add(OldMI->getOperand(i));
951 }
952
953 return Changed;
954}
955
956short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr &MI) const {
958 short TempOpCode = HII->changeAddrMode_io_rr(MI);
959 return HII->changeAddrMode_rr_ur(TempOpCode);
960 }
961 return HII->changeAddrMode_rr_ur(MI);
962}
963
964bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,
965 MachineInstr *AddAslMI,
966 const MachineOperand &ImmOp,
967 unsigned ImmOpNum) {
968 NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);
969
970 LLVM_DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");
971
972 NodeList UNodeList;
973 getAllRealUses(SA, UNodeList);
974
975 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
976 NodeAddr<UseNode *> UseUN = *I;
977 assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) &&
978 "Can't transform this 'AddAsl' instruction!");
979
980 NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);
981 LLVM_DEBUG(dbgs() << "[InstrNode]: "
982 << Print<NodeAddr<InstrNode *>>(UseIA, *DFG) << "\n");
983 MachineInstr *UseMI = UseIA.Addr->getCode();
984 LLVM_DEBUG(dbgs() << "[MI <" << printMBBReference(*UseMI->getParent())
985 << ">]: " << *UseMI << "\n");
986 const MCInstrDesc &UseMID = UseMI->getDesc();
988
989 auto UsePos = MachineBasicBlock::iterator(UseMI);
990 MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator();
991 short NewOpCode = getBaseWithLongOffset(*UseMI);
992 assert(NewOpCode >= 0 && "Invalid New opcode\n");
993
994 unsigned OpStart;
995 unsigned OpEnd = UseMI->getNumOperands();
996
997 MachineBasicBlock *BB = UseMI->getParent();
998 MachineInstrBuilder MIB =
999 BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode));
1000 // change mem(Rs + # ) -> mem(Rt << # + ##)
1001 if (UseMID.mayLoad()) {
1002 MIB.add(UseMI->getOperand(0));
1003 MIB.add(AddAslMI->getOperand(2));
1004 MIB.add(AddAslMI->getOperand(3));
1005 const GlobalValue *GV = ImmOp.getGlobal();
1006 MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm()+ImmOp.getOffset(),
1007 ImmOp.getTargetFlags());
1008 OpStart = 3;
1009 } else if (UseMID.mayStore()) {
1010 MIB.add(AddAslMI->getOperand(2));
1011 MIB.add(AddAslMI->getOperand(3));
1012 const GlobalValue *GV = ImmOp.getGlobal();
1013 MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm()+ImmOp.getOffset(),
1014 ImmOp.getTargetFlags());
1015 MIB.add(UseMI->getOperand(2));
1016 OpStart = 3;
1017 } else
1018 llvm_unreachable("Unhandled instruction");
1019
1020 for (unsigned i = OpStart; i < OpEnd; ++i)
1021 MIB.add(UseMI->getOperand(i));
1022 Deleted.insert(UseMI);
1023 }
1024
1025 return true;
1026}
1027
1028bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,
1029 NodeAddr<UseNode *> UseN,
1030 unsigned UseMOnum) {
1031 const MachineOperand ImmOp = TfrMI->getOperand(1);
1032 const MCInstrDesc &MID = UseMI->getDesc();
1033 unsigned Changed = false;
1034 if (MID.mayLoad())
1035 Changed = changeLoad(UseMI, ImmOp, UseMOnum);
1036 else if (MID.mayStore())
1037 Changed = changeStore(UseMI, ImmOp, UseMOnum);
1038 else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri)
1039 Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);
1040
1041 if (Changed)
1042 Deleted.insert(UseMI);
1043
1044 return Changed;
1045}
1046
1047bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {
1048 bool Changed = false;
1049
1050 for (auto IA : BA.Addr->members(*DFG)) {
1051 if (!DFG->IsCode<NodeAttrs::Stmt>(IA))
1052 continue;
1053
1054 NodeAddr<StmtNode *> SA = IA;
1055 MachineInstr *MI = SA.Addr->getCode();
1056 if ((MI->getOpcode() != Hexagon::A2_tfrsi ||
1057 !MI->getOperand(1).isGlobal()) &&
1058 (MI->getOpcode() != Hexagon::A2_addi ||
1059 !MI->getOperand(2).isImm() || HII->isConstExtended(*MI)))
1060 continue;
1061
1062 LLVM_DEBUG(dbgs() << "[Analyzing " << HII->getName(MI->getOpcode())
1063 << "]: " << *MI << "\n\t[InstrNode]: "
1064 << Print<NodeAddr<InstrNode *>>(IA, *DFG) << '\n');
1065
1066 if (MI->getOpcode() == Hexagon::A2_addi)
1067 Changed |= processAddBases(SA, MI);
1068 NodeList UNodeList;
1069 getAllRealUses(SA, UNodeList);
1070
1071 if (!allValidCandidates(SA, UNodeList))
1072 continue;
1073
1074 // Analyze all uses of 'add'. If the output of 'add' is used as an address
1075 // in the base+immediate addressing mode load/store instructions, see if
1076 // they can be updated to use the immediate value as an offset. Thus,
1077 // providing us the opportunity to eliminate 'add'.
1078 // Ex: Rx= add(Rt,#12)
1079 // memw(Rx+#0) = Rs
1080 // This can be replaced with memw(Rt+#12) = Rs
1081 //
1082 // This transformation is only performed if all uses can be updated and
1083 // the offset isn't required to be constant extended.
1084 if (MI->getOpcode() == Hexagon::A2_addi) {
1085 Changed |= processAddUses(SA, MI, UNodeList);
1086 continue;
1087 }
1088
1089 short SizeInc = 0;
1090 Register DefR = MI->getOperand(0).getReg();
1091 InstrEvalMap InstrEvalResult;
1092
1093 // Analyze all uses and calculate increase in size. Perform the optimization
1094 // only if there is no increase in size.
1095 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))
1096 continue;
1097 if (SizeInc > CodeGrowthLimit)
1098 continue;
1099
1100 bool KeepTfr = false;
1101
1102 LLVM_DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size()
1103 << "\n");
1104 LLVM_DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
1105 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
1106 NodeAddr<UseNode *> UseN = *I;
1107 assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&
1108 "Found a PhiRef node as a real reached use!!");
1109
1110 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);
1111 MachineInstr *UseMI = OwnerN.Addr->getCode();
1112 LLVM_DEBUG(dbgs() << "\t\t[MI <" << printMBBReference(*UseMI->getParent())
1113 << ">]: " << *UseMI << "\n");
1114
1115 int UseMOnum = -1;
1116 unsigned NumOperands = UseMI->getNumOperands();
1117 for (unsigned j = 0; j < NumOperands - 1; ++j) {
1118 const MachineOperand &op = UseMI->getOperand(j);
1119 if (op.isReg() && op.isUse() && DefR == op.getReg())
1120 UseMOnum = j;
1121 }
1122 // It is possible that the register will not be found in any operand.
1123 // This could happen, for example, when DefR = R4, but the used
1124 // register is D2.
1125
1126 // Change UseMI if replacement is possible. If any replacement failed,
1127 // or wasn't attempted, make sure to keep the TFR.
1128 bool Xformed = false;
1129 if (UseMOnum >= 0 && InstrEvalResult[UseMI])
1130 Xformed = xformUseMI(MI, UseMI, UseN, UseMOnum);
1131 Changed |= Xformed;
1132 KeepTfr |= !Xformed;
1133 }
1134 if (!KeepTfr)
1135 Deleted.insert(MI);
1136 }
1137 return Changed;
1138}
1139
1140bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {
1141 if (skipFunction(MF.getFunction()))
1142 return false;
1143
1144 // Perform RDF optimizations only if number of basic blocks in the
1145 // function is less than the limit
1146 if (MF.size() > RDFFuncBlockLimit) {
1147 LLVM_DEBUG(dbgs() << "Skipping " << getPassName()
1148 << ": too many basic blocks\n");
1149 return false;
1150 }
1151
1152 bool Changed = false;
1153 auto &HST = MF.getSubtarget<HexagonSubtarget>();
1154 MRI = &MF.getRegInfo();
1156 HII = HST.getInstrInfo();
1157 HRI = HST.getRegisterInfo();
1158 const auto &MDF = getAnalysis<MachineDominanceFrontier>();
1159 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1160
1161 DataFlowGraph G(MF, *HII, *HRI, *MDT, MDF);
1162 // Need to keep dead phis because we can propagate uses of registers into
1163 // nodes dominated by those would-be phis.
1165 DFG = &G;
1166
1167 Liveness L(*MRI, *DFG);
1168 L.computePhiInfo();
1169 LV = &L;
1170
1171 Deleted.clear();
1172 ProcessedAddiInsts.clear();
1173 NodeAddr<FuncNode *> FA = DFG->getFunc();
1174 LLVM_DEBUG(dbgs() << "==== [RefMap#]=====:\n "
1175 << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");
1176
1177 for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))
1178 Changed |= processBlock(BA);
1179
1180 for (auto *MI : Deleted)
1181 MI->eraseFromParent();
1182
1183 if (Changed) {
1184 G.build();
1185 L.computeLiveIns();
1186 L.resetLiveIns();
1187 L.resetKills();
1188 }
1189
1190 return Changed;
1191}
1192
1193//===----------------------------------------------------------------------===//
1194// Public Constructor Functions
1195//===----------------------------------------------------------------------===//
1196
1198 return new HexagonOptAddrMode();
1199}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
#define op(i)
static cl::opt< int > CodeGrowthLimit("hexagon-amode-growth-limit", cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode " "optimization"))
cl::opt< unsigned > RDFFuncBlockLimit
IRTranslator LLVM IR MI
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
#define I(x, y, z)
Definition MD5.cpp:58
#define G(x, y, z)
Definition MD5.cpp:56
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
if(PassOpts->AAPipeline)
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
#define LLVM_DEBUG(...)
Definition Debug.h:114
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool isPredicated(const MachineInstr &MI) const override
Returns true if the instruction is already predicated.
unsigned getAddrMode(const MachineInstr &MI) const
bool isValidOffset(unsigned Opcode, int Offset, const TargetRegisterInfo *TRI, bool Extend=true) const
bool isConstExtended(const MachineInstr &MI) const
short changeAddrMode_rr_ur(short Opc) const
unsigned getMemAccessSize(const MachineInstr &MI) const
short changeAddrMode_io_abs(short Opc) const
short changeAddrMode_rr_io(short Opc) const
bool isHVXVec(const MachineInstr &MI) const
short changeAddrMode_io_rr(short Opc) const
Describe properties that are true of each instruction in the target description file.
bool mayStore() const
Return true if this instruction could possibly modify memory.
bool mayLoad() const
Return true if this instruction could possibly read memory.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
Analysis pass which computes a MachineDominatorTree.
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
unsigned size() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
const GlobalValue * getGlobal() const
void setImplicit(bool Val=true)
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
unsigned getTargetFlags() const
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
int64_t getOffset() const
Return the offset from the symbol in this operand.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:194
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:169
Changed
#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)
Print(const T &, const DataFlowGraph &) -> Print< T >
uint32_t NodeId
Definition RDFGraph.h:262
std::set< NodeId > NodeSet
Definition RDFGraph.h:551
SmallVector< Node, 4 > NodeList
Definition RDFGraph.h:550
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
FunctionPass * createHexagonOptAddrMode()
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1738
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
static bool IsDef(const Node BA)
Definition RDFGraph.h:825
static bool IsUse(const Node BA)
Definition RDFGraph.h:830
const PhysicalRegisterInfo & getPRI() const
Definition RDFGraph.h:697
static bool IsCode(const Node BA)
Definition RDFGraph.h:821
std::unordered_map< RegisterId, DefStack > DefStackMap
Definition RDFGraph.h:772
NodeAddr< T > addr(NodeId N) const
Definition RDFGraph.h:689
const RefMap & getRealUses(NodeId P) const
Definition RDFLiveness.h:97
NodeAddr< RefNode * > getNearestAliasedRef(RegisterRef RefRR, NodeAddr< InstrNode * > IA)
Find the nearest ref node aliased to RefRR, going upwards in the data flow, starting from the instruc...
std::pair< NodeSet, bool > getAllReachingDefsRec(RegisterRef RefRR, NodeAddr< RefNode * > RefA, NodeSet &Visited, const NodeSet &Defs)
std::unordered_map< RegisterId, NodeRefSet > RefMap
Definition RDFLiveness.h:60
NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr< DefNode * > DefA, const RegisterAggr &DefRRs)
bool alias(RegisterRef RA, RegisterRef RB) const