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