1 //===- HexagonOptAddrMode.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
8 // This implements a Hexagon-specific pass to optimize addressing mode for
9 // load/store instructions.
10 //===----------------------------------------------------------------------===//
12 #include "HexagonInstrInfo.h"
13 #include "HexagonSubtarget.h"
14 #include "MCTargetDesc/HexagonBaseInfo.h"
16 #include "RDFLiveness.h"
17 #include "RDFRegisters.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/DenseSet.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/CodeGen/MachineBasicBlock.h"
22 #include "llvm/CodeGen/MachineDominanceFrontier.h"
23 #include "llvm/CodeGen/MachineDominators.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineFunctionPass.h"
26 #include "llvm/CodeGen/MachineInstr.h"
27 #include "llvm/CodeGen/MachineInstrBuilder.h"
28 #include "llvm/CodeGen/MachineOperand.h"
29 #include "llvm/CodeGen/MachineRegisterInfo.h"
30 #include "llvm/CodeGen/TargetSubtargetInfo.h"
31 #include "llvm/MC/MCInstrDesc.h"
32 #include "llvm/Pass.h"
33 #include "llvm/Support/CommandLine.h"
34 #include "llvm/Support/Debug.h"
35 #include "llvm/Support/ErrorHandling.h"
36 #include "llvm/Support/raw_ostream.h"
40 #define DEBUG_TYPE "opt-addr-mode"
45 static cl::opt
<int> CodeGrowthLimit("hexagon-amode-growth-limit",
46 cl::Hidden
, cl::init(0), cl::desc("Code growth limit for address mode "
51 FunctionPass
*createHexagonOptAddrMode();
52 void initializeHexagonOptAddrModePass(PassRegistry
&);
54 } // end namespace llvm
58 class HexagonOptAddrMode
: public MachineFunctionPass
{
62 HexagonOptAddrMode() : MachineFunctionPass(ID
) {}
64 StringRef
getPassName() const override
{
65 return "Optimize addressing mode of load/store";
68 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
69 MachineFunctionPass::getAnalysisUsage(AU
);
70 AU
.addRequired
<MachineDominatorTree
>();
71 AU
.addRequired
<MachineDominanceFrontier
>();
75 bool runOnMachineFunction(MachineFunction
&MF
) override
;
78 using MISetType
= DenseSet
<MachineInstr
*>;
79 using InstrEvalMap
= DenseMap
<MachineInstr
*, bool>;
81 MachineRegisterInfo
*MRI
= nullptr;
82 const HexagonInstrInfo
*HII
= nullptr;
83 const HexagonRegisterInfo
*HRI
= nullptr;
84 MachineDominatorTree
*MDT
= nullptr;
85 DataFlowGraph
*DFG
= nullptr;
86 DataFlowGraph::DefStackMap DefM
;
87 Liveness
*LV
= nullptr;
90 bool processBlock(NodeAddr
<BlockNode
*> BA
);
91 bool xformUseMI(MachineInstr
*TfrMI
, MachineInstr
*UseMI
,
92 NodeAddr
<UseNode
*> UseN
, unsigned UseMOnum
);
93 bool processAddUses(NodeAddr
<StmtNode
*> AddSN
, MachineInstr
*AddMI
,
94 const NodeList
&UNodeList
);
95 bool updateAddUses(MachineInstr
*AddMI
, MachineInstr
*UseMI
);
96 bool analyzeUses(unsigned DefR
, const NodeList
&UNodeList
,
97 InstrEvalMap
&InstrEvalResult
, short &SizeInc
);
98 bool hasRepForm(MachineInstr
&MI
, unsigned TfrDefR
);
99 bool canRemoveAddasl(NodeAddr
<StmtNode
*> AddAslSN
, MachineInstr
&MI
,
100 const NodeList
&UNodeList
);
101 bool isSafeToExtLR(NodeAddr
<StmtNode
*> SN
, MachineInstr
*MI
,
102 unsigned LRExtReg
, const NodeList
&UNodeList
);
103 void getAllRealUses(NodeAddr
<StmtNode
*> SN
, NodeList
&UNodeList
);
104 bool allValidCandidates(NodeAddr
<StmtNode
*> SA
, NodeList
&UNodeList
);
105 short getBaseWithLongOffset(const MachineInstr
&MI
) const;
106 bool changeStore(MachineInstr
*OldMI
, MachineOperand ImmOp
,
108 bool changeLoad(MachineInstr
*OldMI
, MachineOperand ImmOp
, unsigned ImmOpNum
);
109 bool changeAddAsl(NodeAddr
<UseNode
*> AddAslUN
, MachineInstr
*AddAslMI
,
110 const MachineOperand
&ImmOp
, unsigned ImmOpNum
);
111 bool isValidOffset(MachineInstr
*MI
, int Offset
);
114 } // end anonymous namespace
116 char HexagonOptAddrMode::ID
= 0;
118 INITIALIZE_PASS_BEGIN(HexagonOptAddrMode
, "amode-opt",
119 "Optimize addressing mode", false, false)
120 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree
)
121 INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier
)
122 INITIALIZE_PASS_END(HexagonOptAddrMode
, "amode-opt", "Optimize addressing mode",
125 bool HexagonOptAddrMode::hasRepForm(MachineInstr
&MI
, unsigned TfrDefR
) {
126 const MCInstrDesc
&MID
= MI
.getDesc();
128 if ((!MID
.mayStore() && !MID
.mayLoad()) || HII
->isPredicated(MI
))
131 if (MID
.mayStore()) {
132 MachineOperand StOp
= MI
.getOperand(MI
.getNumOperands() - 1);
133 if (StOp
.isReg() && StOp
.getReg() == TfrDefR
)
137 if (HII
->getAddrMode(MI
) == HexagonII::BaseRegOffset
)
138 // Tranform to Absolute plus register offset.
139 return (HII
->changeAddrMode_rr_ur(MI
) >= 0);
140 else if (HII
->getAddrMode(MI
) == HexagonII::BaseImmOffset
)
141 // Tranform to absolute addressing mode.
142 return (HII
->changeAddrMode_io_abs(MI
) >= 0);
147 // Check if addasl instruction can be removed. This is possible only
148 // if it's feeding to only load/store instructions with base + register
149 // offset as these instruction can be tranformed to use 'absolute plus
150 // shifted register offset'.
153 // Rx = addasl(Rs, Rt, #2)
154 // Rd = memw(Rx + #28)
155 // Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)
157 bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr
<StmtNode
*> AddAslSN
,
159 const NodeList
&UNodeList
) {
160 // check offset size in addasl. if 'offset > 3' return false
161 const MachineOperand
&OffsetOp
= MI
.getOperand(3);
162 if (!OffsetOp
.isImm() || OffsetOp
.getImm() > 3)
165 Register OffsetReg
= MI
.getOperand(2).getReg();
166 RegisterRef OffsetRR
;
167 NodeId OffsetRegRD
= 0;
168 for (NodeAddr
<UseNode
*> UA
: AddAslSN
.Addr
->members_if(DFG
->IsUse
, *DFG
)) {
169 RegisterRef RR
= UA
.Addr
->getRegRef(*DFG
);
170 if (OffsetReg
== RR
.Reg
) {
172 OffsetRegRD
= UA
.Addr
->getReachingDef();
176 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
177 NodeAddr
<UseNode
*> UA
= *I
;
178 NodeAddr
<InstrNode
*> IA
= UA
.Addr
->getOwner(*DFG
);
179 if (UA
.Addr
->getFlags() & NodeAttrs::PhiRef
)
181 NodeAddr
<RefNode
*> AA
= LV
->getNearestAliasedRef(OffsetRR
, IA
);
182 if ((DFG
->IsDef(AA
) && AA
.Id
!= OffsetRegRD
) ||
183 AA
.Addr
->getReachingDef() != OffsetRegRD
)
186 MachineInstr
&UseMI
= *NodeAddr
<StmtNode
*>(IA
).Addr
->getCode();
187 NodeAddr
<DefNode
*> OffsetRegDN
= DFG
->addr
<DefNode
*>(OffsetRegRD
);
188 // Reaching Def to an offset register can't be a phi.
189 if ((OffsetRegDN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
190 MI
.getParent() != UseMI
.getParent())
193 const MCInstrDesc
&UseMID
= UseMI
.getDesc();
194 if ((!UseMID
.mayLoad() && !UseMID
.mayStore()) ||
195 HII
->getAddrMode(UseMI
) != HexagonII::BaseImmOffset
||
196 getBaseWithLongOffset(UseMI
) < 0)
199 // Addasl output can't be a store value.
200 if (UseMID
.mayStore() && UseMI
.getOperand(2).isReg() &&
201 UseMI
.getOperand(2).getReg() == MI
.getOperand(0).getReg())
204 for (auto &Mo
: UseMI
.operands())
211 bool HexagonOptAddrMode::allValidCandidates(NodeAddr
<StmtNode
*> SA
,
212 NodeList
&UNodeList
) {
213 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
214 NodeAddr
<UseNode
*> UN
= *I
;
215 RegisterRef UR
= UN
.Addr
->getRegRef(*DFG
);
216 NodeSet Visited
, Defs
;
217 const auto &P
= LV
->getAllReachingDefsRec(UR
, UN
, Visited
, Defs
);
220 dbgs() << "*** Unable to collect all reaching defs for use ***\n"
221 << PrintNode
<UseNode
*>(UN
, *DFG
) << '\n'
222 << "The program's complexity may exceed the limits.\n";
226 const auto &ReachingDefs
= P
.first
;
227 if (ReachingDefs
.size() > 1) {
229 dbgs() << "*** Multiple Reaching Defs found!!! ***\n";
230 for (auto DI
: ReachingDefs
) {
231 NodeAddr
<UseNode
*> DA
= DFG
->addr
<UseNode
*>(DI
);
232 NodeAddr
<StmtNode
*> TempIA
= DA
.Addr
->getOwner(*DFG
);
233 dbgs() << "\t\t[Reaching Def]: "
234 << Print
<NodeAddr
<InstrNode
*>>(TempIA
, *DFG
) << "\n";
243 void HexagonOptAddrMode::getAllRealUses(NodeAddr
<StmtNode
*> SA
,
244 NodeList
&UNodeList
) {
245 for (NodeAddr
<DefNode
*> DA
: SA
.Addr
->members_if(DFG
->IsDef
, *DFG
)) {
246 LLVM_DEBUG(dbgs() << "\t\t[DefNode]: "
247 << Print
<NodeAddr
<DefNode
*>>(DA
, *DFG
) << "\n");
248 RegisterRef DR
= DFG
->getPRI().normalize(DA
.Addr
->getRegRef(*DFG
));
250 auto UseSet
= LV
->getAllReachedUses(DR
, DA
);
252 for (auto UI
: UseSet
) {
253 NodeAddr
<UseNode
*> UA
= DFG
->addr
<UseNode
*>(UI
);
255 NodeAddr
<StmtNode
*> TempIA
= UA
.Addr
->getOwner(*DFG
);
256 dbgs() << "\t\t\t[Reached Use]: "
257 << Print
<NodeAddr
<InstrNode
*>>(TempIA
, *DFG
) << "\n";
260 if (UA
.Addr
->getFlags() & NodeAttrs::PhiRef
) {
261 NodeAddr
<PhiNode
*> PA
= UA
.Addr
->getOwner(*DFG
);
263 const Liveness::RefMap
&phiUse
= LV
->getRealUses(id
);
264 LLVM_DEBUG(dbgs() << "\t\t\t\tphi real Uses"
265 << Print
<Liveness::RefMap
>(phiUse
, *DFG
) << "\n");
266 if (!phiUse
.empty()) {
267 for (auto I
: phiUse
) {
268 if (!DFG
->getPRI().alias(RegisterRef(I
.first
), DR
))
270 auto phiUseSet
= I
.second
;
271 for (auto phiUI
: phiUseSet
) {
272 NodeAddr
<UseNode
*> phiUA
= DFG
->addr
<UseNode
*>(phiUI
.first
);
273 UNodeList
.push_back(phiUA
);
278 UNodeList
.push_back(UA
);
283 bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr
<StmtNode
*> SN
,
284 MachineInstr
*MI
, unsigned LRExtReg
,
285 const NodeList
&UNodeList
) {
287 NodeId LRExtRegRD
= 0;
288 // Iterate through all the UseNodes in SN and find the reaching def
290 for (NodeAddr
<UseNode
*> UA
: SN
.Addr
->members_if(DFG
->IsUse
, *DFG
)) {
291 RegisterRef RR
= UA
.Addr
->getRegRef(*DFG
);
292 if (LRExtReg
== RR
.Reg
) {
294 LRExtRegRD
= UA
.Addr
->getReachingDef();
298 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
299 NodeAddr
<UseNode
*> UA
= *I
;
300 NodeAddr
<InstrNode
*> IA
= UA
.Addr
->getOwner(*DFG
);
301 // The reaching def of LRExtRR at load/store node should be same as the
302 // one reaching at the SN.
303 if (UA
.Addr
->getFlags() & NodeAttrs::PhiRef
)
305 NodeAddr
<RefNode
*> AA
= LV
->getNearestAliasedRef(LRExtRR
, IA
);
306 if ((DFG
->IsDef(AA
) && AA
.Id
!= LRExtRegRD
) ||
307 AA
.Addr
->getReachingDef() != LRExtRegRD
) {
309 dbgs() << "isSafeToExtLR: Returning false; another reaching def\n");
313 MachineInstr
*UseMI
= NodeAddr
<StmtNode
*>(IA
).Addr
->getCode();
314 NodeAddr
<DefNode
*> LRExtRegDN
= DFG
->addr
<DefNode
*>(LRExtRegRD
);
315 // Reaching Def to LRExtReg can't be a phi.
316 if ((LRExtRegDN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
317 MI
->getParent() != UseMI
->getParent())
323 bool HexagonOptAddrMode::isValidOffset(MachineInstr
*MI
, int Offset
) {
324 unsigned AlignMask
= 0;
325 switch (HII
->getMemAccessSize(*MI
)) {
326 case HexagonII::MemAccessSize::DoubleWordAccess
:
329 case HexagonII::MemAccessSize::WordAccess
:
332 case HexagonII::MemAccessSize::HalfWordAccess
:
335 case HexagonII::MemAccessSize::ByteAccess
:
342 if ((AlignMask
& Offset
) != 0)
344 return HII
->isValidOffset(MI
->getOpcode(), Offset
, HRI
, false);
347 bool HexagonOptAddrMode::processAddUses(NodeAddr
<StmtNode
*> AddSN
,
349 const NodeList
&UNodeList
) {
351 Register AddDefR
= AddMI
->getOperand(0).getReg();
352 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
353 NodeAddr
<UseNode
*> UN
= *I
;
354 NodeAddr
<StmtNode
*> SN
= UN
.Addr
->getOwner(*DFG
);
355 MachineInstr
*MI
= SN
.Addr
->getCode();
356 const MCInstrDesc
&MID
= MI
->getDesc();
357 if ((!MID
.mayLoad() && !MID
.mayStore()) ||
358 HII
->getAddrMode(*MI
) != HexagonII::BaseImmOffset
||
362 MachineOperand BaseOp
= MID
.mayLoad() ? MI
->getOperand(1)
365 if (!BaseOp
.isReg() || BaseOp
.getReg() != AddDefR
)
368 MachineOperand OffsetOp
= MID
.mayLoad() ? MI
->getOperand(2)
370 if (!OffsetOp
.isImm())
373 int64_t newOffset
= OffsetOp
.getImm() + AddMI
->getOperand(2).getImm();
374 if (!isValidOffset(MI
, newOffset
))
377 // Since we'll be extending the live range of Rt in the following example,
378 // make sure that is safe. another definition of Rt doesn't exist between 'add'
379 // and load/store instruction.
381 // Ex: Rx= add(Rt,#10)
383 // will be replaced with => memw(Rt+#10) = Rs
384 Register BaseReg
= AddMI
->getOperand(1).getReg();
385 if (!isSafeToExtLR(AddSN
, AddMI
, BaseReg
, UNodeList
))
389 // Update all the uses of 'add' with the appropriate base and offset
391 bool Changed
= false;
392 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
393 NodeAddr
<UseNode
*> UseN
= *I
;
394 assert(!(UseN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
395 "Found a PhiRef node as a real reached use!!");
397 NodeAddr
<StmtNode
*> OwnerN
= UseN
.Addr
->getOwner(*DFG
);
398 MachineInstr
*UseMI
= OwnerN
.Addr
->getCode();
399 LLVM_DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI
->getParent()->getNumber()
400 << ">]: " << *UseMI
<< "\n");
401 Changed
|= updateAddUses(AddMI
, UseMI
);
405 Deleted
.insert(AddMI
);
410 bool HexagonOptAddrMode::updateAddUses(MachineInstr
*AddMI
,
411 MachineInstr
*UseMI
) {
412 const MachineOperand ImmOp
= AddMI
->getOperand(2);
413 const MachineOperand AddRegOp
= AddMI
->getOperand(1);
414 Register newReg
= AddRegOp
.getReg();
415 const MCInstrDesc
&MID
= UseMI
->getDesc();
417 MachineOperand
&BaseOp
= MID
.mayLoad() ? UseMI
->getOperand(1)
418 : UseMI
->getOperand(0);
419 MachineOperand
&OffsetOp
= MID
.mayLoad() ? UseMI
->getOperand(2)
420 : UseMI
->getOperand(1);
421 BaseOp
.setReg(newReg
);
422 BaseOp
.setIsUndef(AddRegOp
.isUndef());
423 BaseOp
.setImplicit(AddRegOp
.isImplicit());
424 OffsetOp
.setImm(ImmOp
.getImm() + OffsetOp
.getImm());
425 MRI
->clearKillFlags(newReg
);
430 bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR
,
431 const NodeList
&UNodeList
,
432 InstrEvalMap
&InstrEvalResult
,
434 bool KeepTfr
= false;
435 bool HasRepInstr
= false;
436 InstrEvalResult
.clear();
438 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
439 bool CanBeReplaced
= false;
440 NodeAddr
<UseNode
*> UN
= *I
;
441 NodeAddr
<StmtNode
*> SN
= UN
.Addr
->getOwner(*DFG
);
442 MachineInstr
&MI
= *SN
.Addr
->getCode();
443 const MCInstrDesc
&MID
= MI
.getDesc();
444 if ((MID
.mayLoad() || MID
.mayStore())) {
445 if (!hasRepForm(MI
, tfrDefR
)) {
450 CanBeReplaced
= true;
451 } else if (MI
.getOpcode() == Hexagon::S2_addasl_rrri
) {
452 NodeList AddaslUseList
;
454 LLVM_DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI
<< "\n");
455 getAllRealUses(SN
, AddaslUseList
);
456 // Process phi nodes.
457 if (allValidCandidates(SN
, AddaslUseList
) &&
458 canRemoveAddasl(SN
, MI
, AddaslUseList
)) {
459 SizeInc
+= AddaslUseList
.size();
460 SizeInc
-= 1; // Reduce size by 1 as addasl itself can be removed.
461 CanBeReplaced
= true;
465 // Currently, only load/store and addasl are handled.
466 // Some other instructions to consider -
468 // M4_mpyrr_addr -> M4_mpyrr_addi
471 InstrEvalResult
[&MI
] = CanBeReplaced
;
472 HasRepInstr
|= CanBeReplaced
;
475 // Reduce total size by 2 if original tfr can be deleted.
482 bool HexagonOptAddrMode::changeLoad(MachineInstr
*OldMI
, MachineOperand ImmOp
,
484 bool Changed
= false;
485 MachineBasicBlock
*BB
= OldMI
->getParent();
486 auto UsePos
= MachineBasicBlock::iterator(OldMI
);
487 MachineBasicBlock::instr_iterator InsertPt
= UsePos
.getInstrIterator();
490 unsigned OpEnd
= OldMI
->getNumOperands();
491 MachineInstrBuilder MIB
;
494 if (HII
->getAddrMode(*OldMI
) == HexagonII::BaseRegOffset
) {
495 short NewOpCode
= HII
->changeAddrMode_rr_ur(*OldMI
);
496 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
497 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
498 MIB
.add(OldMI
->getOperand(0));
499 MIB
.add(OldMI
->getOperand(2));
500 MIB
.add(OldMI
->getOperand(3));
504 } else if (HII
->getAddrMode(*OldMI
) == HexagonII::BaseImmOffset
&&
505 OldMI
->getOperand(2).isImm()) {
506 short NewOpCode
= HII
->changeAddrMode_io_abs(*OldMI
);
507 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
508 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
))
509 .add(OldMI
->getOperand(0));
510 const GlobalValue
*GV
= ImmOp
.getGlobal();
511 int64_t Offset
= ImmOp
.getOffset() + OldMI
->getOperand(2).getImm();
513 MIB
.addGlobalAddress(GV
, Offset
, ImmOp
.getTargetFlags());
519 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI
<< "\n");
520 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB
<< "\n");
521 } else if (ImmOpNum
== 2) {
522 if (OldMI
->getOperand(3).isImm() && OldMI
->getOperand(3).getImm() == 0) {
523 short NewOpCode
= HII
->changeAddrMode_rr_io(*OldMI
);
524 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
525 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
526 MIB
.add(OldMI
->getOperand(0));
527 MIB
.add(OldMI
->getOperand(1));
531 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI
<< "\n");
532 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB
<< "\n");
537 for (unsigned i
= OpStart
; i
< OpEnd
; ++i
)
538 MIB
.add(OldMI
->getOperand(i
));
543 bool HexagonOptAddrMode::changeStore(MachineInstr
*OldMI
, MachineOperand ImmOp
,
545 bool Changed
= false;
546 unsigned OpStart
= 0;
547 unsigned OpEnd
= OldMI
->getNumOperands();
548 MachineBasicBlock
*BB
= OldMI
->getParent();
549 auto UsePos
= MachineBasicBlock::iterator(OldMI
);
550 MachineBasicBlock::instr_iterator InsertPt
= UsePos
.getInstrIterator();
552 MachineInstrBuilder MIB
;
554 if (HII
->getAddrMode(*OldMI
) == HexagonII::BaseRegOffset
) {
555 short NewOpCode
= HII
->changeAddrMode_rr_ur(*OldMI
);
556 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
557 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
558 MIB
.add(OldMI
->getOperand(1));
559 MIB
.add(OldMI
->getOperand(2));
561 MIB
.add(OldMI
->getOperand(3));
563 } else if (HII
->getAddrMode(*OldMI
) == HexagonII::BaseImmOffset
) {
564 short NewOpCode
= HII
->changeAddrMode_io_abs(*OldMI
);
565 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
566 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
567 const GlobalValue
*GV
= ImmOp
.getGlobal();
568 int64_t Offset
= ImmOp
.getOffset() + OldMI
->getOperand(1).getImm();
569 MIB
.addGlobalAddress(GV
, Offset
, ImmOp
.getTargetFlags());
570 MIB
.add(OldMI
->getOperand(2));
574 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI
<< "\n");
575 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB
<< "\n");
576 } else if (ImmOpNum
== 1 && OldMI
->getOperand(2).getImm() == 0) {
577 short NewOpCode
= HII
->changeAddrMode_rr_io(*OldMI
);
578 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
579 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
580 MIB
.add(OldMI
->getOperand(0));
584 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI
<< "\n");
585 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB
<< "\n");
588 for (unsigned i
= OpStart
; i
< OpEnd
; ++i
)
589 MIB
.add(OldMI
->getOperand(i
));
594 short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr
&MI
) const {
595 if (HII
->getAddrMode(MI
) == HexagonII::BaseImmOffset
) {
596 short TempOpCode
= HII
->changeAddrMode_io_rr(MI
);
597 return HII
->changeAddrMode_rr_ur(TempOpCode
);
599 return HII
->changeAddrMode_rr_ur(MI
);
602 bool HexagonOptAddrMode::changeAddAsl(NodeAddr
<UseNode
*> AddAslUN
,
603 MachineInstr
*AddAslMI
,
604 const MachineOperand
&ImmOp
,
606 NodeAddr
<StmtNode
*> SA
= AddAslUN
.Addr
->getOwner(*DFG
);
608 LLVM_DEBUG(dbgs() << "Processing addasl :" << *AddAslMI
<< "\n");
611 getAllRealUses(SA
, UNodeList
);
613 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
614 NodeAddr
<UseNode
*> UseUN
= *I
;
615 assert(!(UseUN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
616 "Can't transform this 'AddAsl' instruction!");
618 NodeAddr
<StmtNode
*> UseIA
= UseUN
.Addr
->getOwner(*DFG
);
619 LLVM_DEBUG(dbgs() << "[InstrNode]: "
620 << Print
<NodeAddr
<InstrNode
*>>(UseIA
, *DFG
) << "\n");
621 MachineInstr
*UseMI
= UseIA
.Addr
->getCode();
622 LLVM_DEBUG(dbgs() << "[MI <" << printMBBReference(*UseMI
->getParent())
623 << ">]: " << *UseMI
<< "\n");
624 const MCInstrDesc
&UseMID
= UseMI
->getDesc();
625 assert(HII
->getAddrMode(*UseMI
) == HexagonII::BaseImmOffset
);
627 auto UsePos
= MachineBasicBlock::iterator(UseMI
);
628 MachineBasicBlock::instr_iterator InsertPt
= UsePos
.getInstrIterator();
629 short NewOpCode
= getBaseWithLongOffset(*UseMI
);
630 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
633 unsigned OpEnd
= UseMI
->getNumOperands();
635 MachineBasicBlock
*BB
= UseMI
->getParent();
636 MachineInstrBuilder MIB
=
637 BuildMI(*BB
, InsertPt
, UseMI
->getDebugLoc(), HII
->get(NewOpCode
));
638 // change mem(Rs + # ) -> mem(Rt << # + ##)
639 if (UseMID
.mayLoad()) {
640 MIB
.add(UseMI
->getOperand(0));
641 MIB
.add(AddAslMI
->getOperand(2));
642 MIB
.add(AddAslMI
->getOperand(3));
643 const GlobalValue
*GV
= ImmOp
.getGlobal();
644 MIB
.addGlobalAddress(GV
, UseMI
->getOperand(2).getImm()+ImmOp
.getOffset(),
645 ImmOp
.getTargetFlags());
647 } else if (UseMID
.mayStore()) {
648 MIB
.add(AddAslMI
->getOperand(2));
649 MIB
.add(AddAslMI
->getOperand(3));
650 const GlobalValue
*GV
= ImmOp
.getGlobal();
651 MIB
.addGlobalAddress(GV
, UseMI
->getOperand(1).getImm()+ImmOp
.getOffset(),
652 ImmOp
.getTargetFlags());
653 MIB
.add(UseMI
->getOperand(2));
656 llvm_unreachable("Unhandled instruction");
658 for (unsigned i
= OpStart
; i
< OpEnd
; ++i
)
659 MIB
.add(UseMI
->getOperand(i
));
661 Deleted
.insert(UseMI
);
667 bool HexagonOptAddrMode::xformUseMI(MachineInstr
*TfrMI
, MachineInstr
*UseMI
,
668 NodeAddr
<UseNode
*> UseN
,
670 const MachineOperand ImmOp
= TfrMI
->getOperand(1);
671 const MCInstrDesc
&MID
= UseMI
->getDesc();
672 unsigned Changed
= false;
674 Changed
= changeLoad(UseMI
, ImmOp
, UseMOnum
);
675 else if (MID
.mayStore())
676 Changed
= changeStore(UseMI
, ImmOp
, UseMOnum
);
677 else if (UseMI
->getOpcode() == Hexagon::S2_addasl_rrri
)
678 Changed
= changeAddAsl(UseN
, UseMI
, ImmOp
, UseMOnum
);
681 Deleted
.insert(UseMI
);
686 bool HexagonOptAddrMode::processBlock(NodeAddr
<BlockNode
*> BA
) {
687 bool Changed
= false;
689 for (auto IA
: BA
.Addr
->members(*DFG
)) {
690 if (!DFG
->IsCode
<NodeAttrs::Stmt
>(IA
))
693 NodeAddr
<StmtNode
*> SA
= IA
;
694 MachineInstr
*MI
= SA
.Addr
->getCode();
695 if ((MI
->getOpcode() != Hexagon::A2_tfrsi
||
696 !MI
->getOperand(1).isGlobal()) &&
697 (MI
->getOpcode() != Hexagon::A2_addi
||
698 !MI
->getOperand(2).isImm() || HII
->isConstExtended(*MI
)))
701 LLVM_DEBUG(dbgs() << "[Analyzing " << HII
->getName(MI
->getOpcode())
702 << "]: " << *MI
<< "\n\t[InstrNode]: "
703 << Print
<NodeAddr
<InstrNode
*>>(IA
, *DFG
) << '\n');
706 getAllRealUses(SA
, UNodeList
);
708 if (!allValidCandidates(SA
, UNodeList
))
711 // Analyze all uses of 'add'. If the output of 'add' is used as an address
712 // in the base+immediate addressing mode load/store instructions, see if
713 // they can be updated to use the immediate value as an offet. Thus,
714 // providing us the opportunity to eliminate 'add'.
715 // Ex: Rx= add(Rt,#12)
717 // This can be replaced with memw(Rt+#12) = Rs
719 // This transformation is only performed if all uses can be updated and
720 // the offset isn't required to be constant extended.
721 if (MI
->getOpcode() == Hexagon::A2_addi
) {
722 Changed
|= processAddUses(SA
, MI
, UNodeList
);
727 Register DefR
= MI
->getOperand(0).getReg();
728 InstrEvalMap InstrEvalResult
;
730 // Analyze all uses and calculate increase in size. Perform the optimization
731 // only if there is no increase in size.
732 if (!analyzeUses(DefR
, UNodeList
, InstrEvalResult
, SizeInc
))
734 if (SizeInc
> CodeGrowthLimit
)
737 bool KeepTfr
= false;
739 LLVM_DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList
.size()
741 LLVM_DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
742 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
743 NodeAddr
<UseNode
*> UseN
= *I
;
744 assert(!(UseN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
745 "Found a PhiRef node as a real reached use!!");
747 NodeAddr
<StmtNode
*> OwnerN
= UseN
.Addr
->getOwner(*DFG
);
748 MachineInstr
*UseMI
= OwnerN
.Addr
->getCode();
749 LLVM_DEBUG(dbgs() << "\t\t[MI <" << printMBBReference(*UseMI
->getParent())
750 << ">]: " << *UseMI
<< "\n");
753 unsigned NumOperands
= UseMI
->getNumOperands();
754 for (unsigned j
= 0; j
< NumOperands
- 1; ++j
) {
755 const MachineOperand
&op
= UseMI
->getOperand(j
);
756 if (op
.isReg() && op
.isUse() && DefR
== op
.getReg())
759 // It is possible that the register will not be found in any operand.
760 // This could happen, for example, when DefR = R4, but the used
763 // Change UseMI if replacement is possible. If any replacement failed,
764 // or wasn't attempted, make sure to keep the TFR.
765 bool Xformed
= false;
766 if (UseMOnum
>= 0 && InstrEvalResult
[UseMI
])
767 Xformed
= xformUseMI(MI
, UseMI
, UseN
, UseMOnum
);
777 bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction
&MF
) {
778 if (skipFunction(MF
.getFunction()))
781 bool Changed
= false;
782 auto &HST
= MF
.getSubtarget
<HexagonSubtarget
>();
783 MRI
= &MF
.getRegInfo();
784 HII
= HST
.getInstrInfo();
785 HRI
= HST
.getRegisterInfo();
786 const auto &MDF
= getAnalysis
<MachineDominanceFrontier
>();
787 MDT
= &getAnalysis
<MachineDominatorTree
>();
788 const TargetOperandInfo
TOI(*HII
);
790 DataFlowGraph
G(MF
, *HII
, *HRI
, *MDT
, MDF
, TOI
);
791 // Need to keep dead phis because we can propagate uses of registers into
792 // nodes dominated by those would-be phis.
793 G
.build(BuildOptions::KeepDeadPhis
);
796 Liveness
L(*MRI
, *DFG
);
801 NodeAddr
<FuncNode
*> FA
= DFG
->getFunc();
802 LLVM_DEBUG(dbgs() << "==== [RefMap#]=====:\n "
803 << Print
<NodeAddr
<FuncNode
*>>(FA
, *DFG
) << "\n");
805 for (NodeAddr
<BlockNode
*> BA
: FA
.Addr
->members(*DFG
))
806 Changed
|= processBlock(BA
);
808 for (auto MI
: Deleted
)
809 MI
->eraseFromParent();
821 //===----------------------------------------------------------------------===//
822 // Public Constructor Functions
823 //===----------------------------------------------------------------------===//
825 FunctionPass
*llvm::createHexagonOptAddrMode() {
826 return new HexagonOptAddrMode();