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"
15 #include "llvm/ADT/DenseMap.h"
16 #include "llvm/ADT/DenseSet.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineDominanceFrontier.h"
20 #include "llvm/CodeGen/MachineDominators.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineFunctionPass.h"
23 #include "llvm/CodeGen/MachineInstr.h"
24 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #include "llvm/CodeGen/MachineOperand.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/CodeGen/RDFGraph.h"
28 #include "llvm/CodeGen/RDFLiveness.h"
29 #include "llvm/CodeGen/RDFRegisters.h"
30 #include "llvm/CodeGen/TargetSubtargetInfo.h"
31 #include "llvm/InitializePasses.h"
32 #include "llvm/MC/MCInstrDesc.h"
33 #include "llvm/Pass.h"
34 #include "llvm/Support/CommandLine.h"
35 #include "llvm/Support/Debug.h"
36 #include "llvm/Support/ErrorHandling.h"
37 #include "llvm/Support/raw_ostream.h"
41 #define DEBUG_TYPE "opt-addr-mode"
46 static cl::opt
<int> CodeGrowthLimit("hexagon-amode-growth-limit",
47 cl::Hidden
, cl::init(0), cl::desc("Code growth limit for address mode "
52 FunctionPass
*createHexagonOptAddrMode();
53 void initializeHexagonOptAddrModePass(PassRegistry
&);
55 } // end namespace llvm
59 class HexagonOptAddrMode
: public MachineFunctionPass
{
63 HexagonOptAddrMode() : MachineFunctionPass(ID
) {}
65 StringRef
getPassName() const override
{
66 return "Optimize addressing mode of load/store";
69 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
70 MachineFunctionPass::getAnalysisUsage(AU
);
71 AU
.addRequired
<MachineDominatorTree
>();
72 AU
.addRequired
<MachineDominanceFrontier
>();
76 bool runOnMachineFunction(MachineFunction
&MF
) override
;
79 using MISetType
= DenseSet
<MachineInstr
*>;
80 using InstrEvalMap
= DenseMap
<MachineInstr
*, bool>;
82 MachineRegisterInfo
*MRI
= nullptr;
83 const HexagonInstrInfo
*HII
= nullptr;
84 const HexagonRegisterInfo
*HRI
= nullptr;
85 MachineDominatorTree
*MDT
= nullptr;
86 DataFlowGraph
*DFG
= nullptr;
87 DataFlowGraph::DefStackMap DefM
;
88 Liveness
*LV
= nullptr;
91 bool processBlock(NodeAddr
<BlockNode
*> BA
);
92 bool xformUseMI(MachineInstr
*TfrMI
, MachineInstr
*UseMI
,
93 NodeAddr
<UseNode
*> UseN
, unsigned UseMOnum
);
94 bool processAddUses(NodeAddr
<StmtNode
*> AddSN
, MachineInstr
*AddMI
,
95 const NodeList
&UNodeList
);
96 bool updateAddUses(MachineInstr
*AddMI
, MachineInstr
*UseMI
);
97 bool analyzeUses(unsigned DefR
, const NodeList
&UNodeList
,
98 InstrEvalMap
&InstrEvalResult
, short &SizeInc
);
99 bool hasRepForm(MachineInstr
&MI
, unsigned TfrDefR
);
100 bool canRemoveAddasl(NodeAddr
<StmtNode
*> AddAslSN
, MachineInstr
&MI
,
101 const NodeList
&UNodeList
);
102 bool isSafeToExtLR(NodeAddr
<StmtNode
*> SN
, MachineInstr
*MI
,
103 unsigned LRExtReg
, const NodeList
&UNodeList
);
104 void getAllRealUses(NodeAddr
<StmtNode
*> SN
, NodeList
&UNodeList
);
105 bool allValidCandidates(NodeAddr
<StmtNode
*> SA
, NodeList
&UNodeList
);
106 short getBaseWithLongOffset(const MachineInstr
&MI
) const;
107 bool changeStore(MachineInstr
*OldMI
, MachineOperand ImmOp
,
109 bool changeLoad(MachineInstr
*OldMI
, MachineOperand ImmOp
, unsigned ImmOpNum
);
110 bool changeAddAsl(NodeAddr
<UseNode
*> AddAslUN
, MachineInstr
*AddAslMI
,
111 const MachineOperand
&ImmOp
, unsigned ImmOpNum
);
112 bool isValidOffset(MachineInstr
*MI
, int Offset
);
115 } // end anonymous namespace
117 char HexagonOptAddrMode::ID
= 0;
119 INITIALIZE_PASS_BEGIN(HexagonOptAddrMode
, "amode-opt",
120 "Optimize addressing mode", false, false)
121 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree
)
122 INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier
)
123 INITIALIZE_PASS_END(HexagonOptAddrMode
, "amode-opt", "Optimize addressing mode",
126 bool HexagonOptAddrMode::hasRepForm(MachineInstr
&MI
, unsigned TfrDefR
) {
127 const MCInstrDesc
&MID
= MI
.getDesc();
129 if ((!MID
.mayStore() && !MID
.mayLoad()) || HII
->isPredicated(MI
))
132 if (MID
.mayStore()) {
133 MachineOperand StOp
= MI
.getOperand(MI
.getNumOperands() - 1);
134 if (StOp
.isReg() && StOp
.getReg() == TfrDefR
)
138 if (HII
->getAddrMode(MI
) == HexagonII::BaseRegOffset
)
139 // Tranform to Absolute plus register offset.
140 return (HII
->changeAddrMode_rr_ur(MI
) >= 0);
141 else if (HII
->getAddrMode(MI
) == HexagonII::BaseImmOffset
)
142 // Tranform to absolute addressing mode.
143 return (HII
->changeAddrMode_io_abs(MI
) >= 0);
148 // Check if addasl instruction can be removed. This is possible only
149 // if it's feeding to only load/store instructions with base + register
150 // offset as these instruction can be tranformed to use 'absolute plus
151 // shifted register offset'.
154 // Rx = addasl(Rs, Rt, #2)
155 // Rd = memw(Rx + #28)
156 // Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28)
158 bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr
<StmtNode
*> AddAslSN
,
160 const NodeList
&UNodeList
) {
161 // check offset size in addasl. if 'offset > 3' return false
162 const MachineOperand
&OffsetOp
= MI
.getOperand(3);
163 if (!OffsetOp
.isImm() || OffsetOp
.getImm() > 3)
166 Register OffsetReg
= MI
.getOperand(2).getReg();
167 RegisterRef OffsetRR
;
168 NodeId OffsetRegRD
= 0;
169 for (NodeAddr
<UseNode
*> UA
: AddAslSN
.Addr
->members_if(DFG
->IsUse
, *DFG
)) {
170 RegisterRef RR
= UA
.Addr
->getRegRef(*DFG
);
171 if (OffsetReg
== RR
.Reg
) {
173 OffsetRegRD
= UA
.Addr
->getReachingDef();
177 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
178 NodeAddr
<UseNode
*> UA
= *I
;
179 NodeAddr
<InstrNode
*> IA
= UA
.Addr
->getOwner(*DFG
);
180 if (UA
.Addr
->getFlags() & NodeAttrs::PhiRef
)
182 NodeAddr
<RefNode
*> AA
= LV
->getNearestAliasedRef(OffsetRR
, IA
);
183 if ((DFG
->IsDef(AA
) && AA
.Id
!= OffsetRegRD
) ||
184 AA
.Addr
->getReachingDef() != OffsetRegRD
)
187 MachineInstr
&UseMI
= *NodeAddr
<StmtNode
*>(IA
).Addr
->getCode();
188 NodeAddr
<DefNode
*> OffsetRegDN
= DFG
->addr
<DefNode
*>(OffsetRegRD
);
189 // Reaching Def to an offset register can't be a phi.
190 if ((OffsetRegDN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
191 MI
.getParent() != UseMI
.getParent())
194 const MCInstrDesc
&UseMID
= UseMI
.getDesc();
195 if ((!UseMID
.mayLoad() && !UseMID
.mayStore()) ||
196 HII
->getAddrMode(UseMI
) != HexagonII::BaseImmOffset
||
197 getBaseWithLongOffset(UseMI
) < 0)
200 // Addasl output can't be a store value.
201 if (UseMID
.mayStore() && UseMI
.getOperand(2).isReg() &&
202 UseMI
.getOperand(2).getReg() == MI
.getOperand(0).getReg())
205 for (auto &Mo
: UseMI
.operands())
212 bool HexagonOptAddrMode::allValidCandidates(NodeAddr
<StmtNode
*> SA
,
213 NodeList
&UNodeList
) {
214 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
215 NodeAddr
<UseNode
*> UN
= *I
;
216 RegisterRef UR
= UN
.Addr
->getRegRef(*DFG
);
217 NodeSet Visited
, Defs
;
218 const auto &P
= LV
->getAllReachingDefsRec(UR
, UN
, Visited
, Defs
);
221 dbgs() << "*** Unable to collect all reaching defs for use ***\n"
222 << PrintNode
<UseNode
*>(UN
, *DFG
) << '\n'
223 << "The program's complexity may exceed the limits.\n";
227 const auto &ReachingDefs
= P
.first
;
228 if (ReachingDefs
.size() > 1) {
230 dbgs() << "*** Multiple Reaching Defs found!!! ***\n";
231 for (auto DI
: ReachingDefs
) {
232 NodeAddr
<UseNode
*> DA
= DFG
->addr
<UseNode
*>(DI
);
233 NodeAddr
<StmtNode
*> TempIA
= DA
.Addr
->getOwner(*DFG
);
234 dbgs() << "\t\t[Reaching Def]: "
235 << Print
<NodeAddr
<InstrNode
*>>(TempIA
, *DFG
) << "\n";
244 void HexagonOptAddrMode::getAllRealUses(NodeAddr
<StmtNode
*> SA
,
245 NodeList
&UNodeList
) {
246 for (NodeAddr
<DefNode
*> DA
: SA
.Addr
->members_if(DFG
->IsDef
, *DFG
)) {
247 LLVM_DEBUG(dbgs() << "\t\t[DefNode]: "
248 << Print
<NodeAddr
<DefNode
*>>(DA
, *DFG
) << "\n");
249 RegisterRef DR
= DA
.Addr
->getRegRef(*DFG
);
251 auto UseSet
= LV
->getAllReachedUses(DR
, DA
);
253 for (auto UI
: UseSet
) {
254 NodeAddr
<UseNode
*> UA
= DFG
->addr
<UseNode
*>(UI
);
256 NodeAddr
<StmtNode
*> TempIA
= UA
.Addr
->getOwner(*DFG
);
257 dbgs() << "\t\t\t[Reached Use]: "
258 << Print
<NodeAddr
<InstrNode
*>>(TempIA
, *DFG
) << "\n";
261 if (UA
.Addr
->getFlags() & NodeAttrs::PhiRef
) {
262 NodeAddr
<PhiNode
*> PA
= UA
.Addr
->getOwner(*DFG
);
264 const Liveness::RefMap
&phiUse
= LV
->getRealUses(id
);
265 LLVM_DEBUG(dbgs() << "\t\t\t\tphi real Uses"
266 << Print
<Liveness::RefMap
>(phiUse
, *DFG
) << "\n");
267 if (!phiUse
.empty()) {
268 for (auto I
: phiUse
) {
269 if (!DFG
->getPRI().alias(RegisterRef(I
.first
), DR
))
271 auto phiUseSet
= I
.second
;
272 for (auto phiUI
: phiUseSet
) {
273 NodeAddr
<UseNode
*> phiUA
= DFG
->addr
<UseNode
*>(phiUI
.first
);
274 UNodeList
.push_back(phiUA
);
279 UNodeList
.push_back(UA
);
284 bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr
<StmtNode
*> SN
,
285 MachineInstr
*MI
, unsigned LRExtReg
,
286 const NodeList
&UNodeList
) {
288 NodeId LRExtRegRD
= 0;
289 // Iterate through all the UseNodes in SN and find the reaching def
291 for (NodeAddr
<UseNode
*> UA
: SN
.Addr
->members_if(DFG
->IsUse
, *DFG
)) {
292 RegisterRef RR
= UA
.Addr
->getRegRef(*DFG
);
293 if (LRExtReg
== RR
.Reg
) {
295 LRExtRegRD
= UA
.Addr
->getReachingDef();
299 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
300 NodeAddr
<UseNode
*> UA
= *I
;
301 NodeAddr
<InstrNode
*> IA
= UA
.Addr
->getOwner(*DFG
);
302 // The reaching def of LRExtRR at load/store node should be same as the
303 // one reaching at the SN.
304 if (UA
.Addr
->getFlags() & NodeAttrs::PhiRef
)
306 NodeAddr
<RefNode
*> AA
= LV
->getNearestAliasedRef(LRExtRR
, IA
);
307 if ((DFG
->IsDef(AA
) && AA
.Id
!= LRExtRegRD
) ||
308 AA
.Addr
->getReachingDef() != LRExtRegRD
) {
310 dbgs() << "isSafeToExtLR: Returning false; another reaching def\n");
314 MachineInstr
*UseMI
= NodeAddr
<StmtNode
*>(IA
).Addr
->getCode();
315 NodeAddr
<DefNode
*> LRExtRegDN
= DFG
->addr
<DefNode
*>(LRExtRegRD
);
316 // Reaching Def to LRExtReg can't be a phi.
317 if ((LRExtRegDN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
318 MI
->getParent() != UseMI
->getParent())
324 bool HexagonOptAddrMode::isValidOffset(MachineInstr
*MI
, int Offset
) {
325 unsigned AlignMask
= 0;
326 switch (HII
->getMemAccessSize(*MI
)) {
327 case HexagonII::MemAccessSize::DoubleWordAccess
:
330 case HexagonII::MemAccessSize::WordAccess
:
333 case HexagonII::MemAccessSize::HalfWordAccess
:
336 case HexagonII::MemAccessSize::ByteAccess
:
343 if ((AlignMask
& Offset
) != 0)
345 return HII
->isValidOffset(MI
->getOpcode(), Offset
, HRI
, false);
348 bool HexagonOptAddrMode::processAddUses(NodeAddr
<StmtNode
*> AddSN
,
350 const NodeList
&UNodeList
) {
352 Register AddDefR
= AddMI
->getOperand(0).getReg();
353 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
354 NodeAddr
<UseNode
*> UN
= *I
;
355 NodeAddr
<StmtNode
*> SN
= UN
.Addr
->getOwner(*DFG
);
356 MachineInstr
*MI
= SN
.Addr
->getCode();
357 const MCInstrDesc
&MID
= MI
->getDesc();
358 if ((!MID
.mayLoad() && !MID
.mayStore()) ||
359 HII
->getAddrMode(*MI
) != HexagonII::BaseImmOffset
||
363 MachineOperand BaseOp
= MID
.mayLoad() ? MI
->getOperand(1)
366 if (!BaseOp
.isReg() || BaseOp
.getReg() != AddDefR
)
369 MachineOperand OffsetOp
= MID
.mayLoad() ? MI
->getOperand(2)
371 if (!OffsetOp
.isImm())
374 int64_t newOffset
= OffsetOp
.getImm() + AddMI
->getOperand(2).getImm();
375 if (!isValidOffset(MI
, newOffset
))
378 // Since we'll be extending the live range of Rt in the following example,
379 // make sure that is safe. another definition of Rt doesn't exist between 'add'
380 // and load/store instruction.
382 // Ex: Rx= add(Rt,#10)
384 // will be replaced with => memw(Rt+#10) = Rs
385 Register BaseReg
= AddMI
->getOperand(1).getReg();
386 if (!isSafeToExtLR(AddSN
, AddMI
, BaseReg
, UNodeList
))
390 // Update all the uses of 'add' with the appropriate base and offset
392 bool Changed
= false;
393 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
394 NodeAddr
<UseNode
*> UseN
= *I
;
395 assert(!(UseN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
396 "Found a PhiRef node as a real reached use!!");
398 NodeAddr
<StmtNode
*> OwnerN
= UseN
.Addr
->getOwner(*DFG
);
399 MachineInstr
*UseMI
= OwnerN
.Addr
->getCode();
400 LLVM_DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI
->getParent()->getNumber()
401 << ">]: " << *UseMI
<< "\n");
402 Changed
|= updateAddUses(AddMI
, UseMI
);
406 Deleted
.insert(AddMI
);
411 bool HexagonOptAddrMode::updateAddUses(MachineInstr
*AddMI
,
412 MachineInstr
*UseMI
) {
413 const MachineOperand ImmOp
= AddMI
->getOperand(2);
414 const MachineOperand AddRegOp
= AddMI
->getOperand(1);
415 Register newReg
= AddRegOp
.getReg();
416 const MCInstrDesc
&MID
= UseMI
->getDesc();
418 MachineOperand
&BaseOp
= MID
.mayLoad() ? UseMI
->getOperand(1)
419 : UseMI
->getOperand(0);
420 MachineOperand
&OffsetOp
= MID
.mayLoad() ? UseMI
->getOperand(2)
421 : UseMI
->getOperand(1);
422 BaseOp
.setReg(newReg
);
423 BaseOp
.setIsUndef(AddRegOp
.isUndef());
424 BaseOp
.setImplicit(AddRegOp
.isImplicit());
425 OffsetOp
.setImm(ImmOp
.getImm() + OffsetOp
.getImm());
426 MRI
->clearKillFlags(newReg
);
431 bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR
,
432 const NodeList
&UNodeList
,
433 InstrEvalMap
&InstrEvalResult
,
435 bool KeepTfr
= false;
436 bool HasRepInstr
= false;
437 InstrEvalResult
.clear();
439 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
440 bool CanBeReplaced
= false;
441 NodeAddr
<UseNode
*> UN
= *I
;
442 NodeAddr
<StmtNode
*> SN
= UN
.Addr
->getOwner(*DFG
);
443 MachineInstr
&MI
= *SN
.Addr
->getCode();
444 const MCInstrDesc
&MID
= MI
.getDesc();
445 if ((MID
.mayLoad() || MID
.mayStore())) {
446 if (!hasRepForm(MI
, tfrDefR
)) {
451 CanBeReplaced
= true;
452 } else if (MI
.getOpcode() == Hexagon::S2_addasl_rrri
) {
453 NodeList AddaslUseList
;
455 LLVM_DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI
<< "\n");
456 getAllRealUses(SN
, AddaslUseList
);
457 // Process phi nodes.
458 if (allValidCandidates(SN
, AddaslUseList
) &&
459 canRemoveAddasl(SN
, MI
, AddaslUseList
)) {
460 SizeInc
+= AddaslUseList
.size();
461 SizeInc
-= 1; // Reduce size by 1 as addasl itself can be removed.
462 CanBeReplaced
= true;
466 // Currently, only load/store and addasl are handled.
467 // Some other instructions to consider -
469 // M4_mpyrr_addr -> M4_mpyrr_addi
472 InstrEvalResult
[&MI
] = CanBeReplaced
;
473 HasRepInstr
|= CanBeReplaced
;
476 // Reduce total size by 2 if original tfr can be deleted.
483 bool HexagonOptAddrMode::changeLoad(MachineInstr
*OldMI
, MachineOperand ImmOp
,
485 bool Changed
= false;
486 MachineBasicBlock
*BB
= OldMI
->getParent();
487 auto UsePos
= MachineBasicBlock::iterator(OldMI
);
488 MachineBasicBlock::instr_iterator InsertPt
= UsePos
.getInstrIterator();
491 unsigned OpEnd
= OldMI
->getNumOperands();
492 MachineInstrBuilder MIB
;
495 if (HII
->getAddrMode(*OldMI
) == HexagonII::BaseRegOffset
) {
496 short NewOpCode
= HII
->changeAddrMode_rr_ur(*OldMI
);
497 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
498 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
499 MIB
.add(OldMI
->getOperand(0));
500 MIB
.add(OldMI
->getOperand(2));
501 MIB
.add(OldMI
->getOperand(3));
505 } else if (HII
->getAddrMode(*OldMI
) == HexagonII::BaseImmOffset
&&
506 OldMI
->getOperand(2).isImm()) {
507 short NewOpCode
= HII
->changeAddrMode_io_abs(*OldMI
);
508 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
509 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
))
510 .add(OldMI
->getOperand(0));
511 const GlobalValue
*GV
= ImmOp
.getGlobal();
512 int64_t Offset
= ImmOp
.getOffset() + OldMI
->getOperand(2).getImm();
514 MIB
.addGlobalAddress(GV
, Offset
, ImmOp
.getTargetFlags());
520 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI
<< "\n");
521 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB
<< "\n");
522 } else if (ImmOpNum
== 2) {
523 if (OldMI
->getOperand(3).isImm() && OldMI
->getOperand(3).getImm() == 0) {
524 short NewOpCode
= HII
->changeAddrMode_rr_io(*OldMI
);
525 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
526 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
527 MIB
.add(OldMI
->getOperand(0));
528 MIB
.add(OldMI
->getOperand(1));
532 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI
<< "\n");
533 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB
<< "\n");
538 for (unsigned i
= OpStart
; i
< OpEnd
; ++i
)
539 MIB
.add(OldMI
->getOperand(i
));
544 bool HexagonOptAddrMode::changeStore(MachineInstr
*OldMI
, MachineOperand ImmOp
,
546 bool Changed
= false;
547 unsigned OpStart
= 0;
548 unsigned OpEnd
= OldMI
->getNumOperands();
549 MachineBasicBlock
*BB
= OldMI
->getParent();
550 auto UsePos
= MachineBasicBlock::iterator(OldMI
);
551 MachineBasicBlock::instr_iterator InsertPt
= UsePos
.getInstrIterator();
553 MachineInstrBuilder MIB
;
555 if (HII
->getAddrMode(*OldMI
) == HexagonII::BaseRegOffset
) {
556 short NewOpCode
= HII
->changeAddrMode_rr_ur(*OldMI
);
557 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
558 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
559 MIB
.add(OldMI
->getOperand(1));
560 MIB
.add(OldMI
->getOperand(2));
562 MIB
.add(OldMI
->getOperand(3));
565 } else if (HII
->getAddrMode(*OldMI
) == HexagonII::BaseImmOffset
) {
566 short NewOpCode
= HII
->changeAddrMode_io_abs(*OldMI
);
567 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
568 MIB
= BuildMI(*BB
, InsertPt
, OldMI
->getDebugLoc(), HII
->get(NewOpCode
));
569 const GlobalValue
*GV
= ImmOp
.getGlobal();
570 int64_t Offset
= ImmOp
.getOffset() + OldMI
->getOperand(1).getImm();
571 MIB
.addGlobalAddress(GV
, Offset
, ImmOp
.getTargetFlags());
572 MIB
.add(OldMI
->getOperand(2));
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));
586 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI
<< "\n");
587 LLVM_DEBUG(dbgs() << "[TO]: " << *MIB
<< "\n");
589 for (unsigned i
= OpStart
; i
< OpEnd
; ++i
)
590 MIB
.add(OldMI
->getOperand(i
));
596 short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr
&MI
) const {
597 if (HII
->getAddrMode(MI
) == HexagonII::BaseImmOffset
) {
598 short TempOpCode
= HII
->changeAddrMode_io_rr(MI
);
599 return HII
->changeAddrMode_rr_ur(TempOpCode
);
601 return HII
->changeAddrMode_rr_ur(MI
);
604 bool HexagonOptAddrMode::changeAddAsl(NodeAddr
<UseNode
*> AddAslUN
,
605 MachineInstr
*AddAslMI
,
606 const MachineOperand
&ImmOp
,
608 NodeAddr
<StmtNode
*> SA
= AddAslUN
.Addr
->getOwner(*DFG
);
610 LLVM_DEBUG(dbgs() << "Processing addasl :" << *AddAslMI
<< "\n");
613 getAllRealUses(SA
, UNodeList
);
615 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
616 NodeAddr
<UseNode
*> UseUN
= *I
;
617 assert(!(UseUN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
618 "Can't transform this 'AddAsl' instruction!");
620 NodeAddr
<StmtNode
*> UseIA
= UseUN
.Addr
->getOwner(*DFG
);
621 LLVM_DEBUG(dbgs() << "[InstrNode]: "
622 << Print
<NodeAddr
<InstrNode
*>>(UseIA
, *DFG
) << "\n");
623 MachineInstr
*UseMI
= UseIA
.Addr
->getCode();
624 LLVM_DEBUG(dbgs() << "[MI <" << printMBBReference(*UseMI
->getParent())
625 << ">]: " << *UseMI
<< "\n");
626 const MCInstrDesc
&UseMID
= UseMI
->getDesc();
627 assert(HII
->getAddrMode(*UseMI
) == HexagonII::BaseImmOffset
);
629 auto UsePos
= MachineBasicBlock::iterator(UseMI
);
630 MachineBasicBlock::instr_iterator InsertPt
= UsePos
.getInstrIterator();
631 short NewOpCode
= getBaseWithLongOffset(*UseMI
);
632 assert(NewOpCode
>= 0 && "Invalid New opcode\n");
635 unsigned OpEnd
= UseMI
->getNumOperands();
637 MachineBasicBlock
*BB
= UseMI
->getParent();
638 MachineInstrBuilder MIB
=
639 BuildMI(*BB
, InsertPt
, UseMI
->getDebugLoc(), HII
->get(NewOpCode
));
640 // change mem(Rs + # ) -> mem(Rt << # + ##)
641 if (UseMID
.mayLoad()) {
642 MIB
.add(UseMI
->getOperand(0));
643 MIB
.add(AddAslMI
->getOperand(2));
644 MIB
.add(AddAslMI
->getOperand(3));
645 const GlobalValue
*GV
= ImmOp
.getGlobal();
646 MIB
.addGlobalAddress(GV
, UseMI
->getOperand(2).getImm()+ImmOp
.getOffset(),
647 ImmOp
.getTargetFlags());
649 } else if (UseMID
.mayStore()) {
650 MIB
.add(AddAslMI
->getOperand(2));
651 MIB
.add(AddAslMI
->getOperand(3));
652 const GlobalValue
*GV
= ImmOp
.getGlobal();
653 MIB
.addGlobalAddress(GV
, UseMI
->getOperand(1).getImm()+ImmOp
.getOffset(),
654 ImmOp
.getTargetFlags());
655 MIB
.add(UseMI
->getOperand(2));
658 llvm_unreachable("Unhandled instruction");
660 for (unsigned i
= OpStart
; i
< OpEnd
; ++i
)
661 MIB
.add(UseMI
->getOperand(i
));
663 Deleted
.insert(UseMI
);
669 bool HexagonOptAddrMode::xformUseMI(MachineInstr
*TfrMI
, MachineInstr
*UseMI
,
670 NodeAddr
<UseNode
*> UseN
,
672 const MachineOperand ImmOp
= TfrMI
->getOperand(1);
673 const MCInstrDesc
&MID
= UseMI
->getDesc();
674 unsigned Changed
= false;
676 Changed
= changeLoad(UseMI
, ImmOp
, UseMOnum
);
677 else if (MID
.mayStore())
678 Changed
= changeStore(UseMI
, ImmOp
, UseMOnum
);
679 else if (UseMI
->getOpcode() == Hexagon::S2_addasl_rrri
)
680 Changed
= changeAddAsl(UseN
, UseMI
, ImmOp
, UseMOnum
);
683 Deleted
.insert(UseMI
);
688 bool HexagonOptAddrMode::processBlock(NodeAddr
<BlockNode
*> BA
) {
689 bool Changed
= false;
691 for (auto IA
: BA
.Addr
->members(*DFG
)) {
692 if (!DFG
->IsCode
<NodeAttrs::Stmt
>(IA
))
695 NodeAddr
<StmtNode
*> SA
= IA
;
696 MachineInstr
*MI
= SA
.Addr
->getCode();
697 if ((MI
->getOpcode() != Hexagon::A2_tfrsi
||
698 !MI
->getOperand(1).isGlobal()) &&
699 (MI
->getOpcode() != Hexagon::A2_addi
||
700 !MI
->getOperand(2).isImm() || HII
->isConstExtended(*MI
)))
703 LLVM_DEBUG(dbgs() << "[Analyzing " << HII
->getName(MI
->getOpcode())
704 << "]: " << *MI
<< "\n\t[InstrNode]: "
705 << Print
<NodeAddr
<InstrNode
*>>(IA
, *DFG
) << '\n');
708 getAllRealUses(SA
, UNodeList
);
710 if (!allValidCandidates(SA
, UNodeList
))
713 // Analyze all uses of 'add'. If the output of 'add' is used as an address
714 // in the base+immediate addressing mode load/store instructions, see if
715 // they can be updated to use the immediate value as an offet. Thus,
716 // providing us the opportunity to eliminate 'add'.
717 // Ex: Rx= add(Rt,#12)
719 // This can be replaced with memw(Rt+#12) = Rs
721 // This transformation is only performed if all uses can be updated and
722 // the offset isn't required to be constant extended.
723 if (MI
->getOpcode() == Hexagon::A2_addi
) {
724 Changed
|= processAddUses(SA
, MI
, UNodeList
);
729 Register DefR
= MI
->getOperand(0).getReg();
730 InstrEvalMap InstrEvalResult
;
732 // Analyze all uses and calculate increase in size. Perform the optimization
733 // only if there is no increase in size.
734 if (!analyzeUses(DefR
, UNodeList
, InstrEvalResult
, SizeInc
))
736 if (SizeInc
> CodeGrowthLimit
)
739 bool KeepTfr
= false;
741 LLVM_DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList
.size()
743 LLVM_DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");
744 for (auto I
= UNodeList
.rbegin(), E
= UNodeList
.rend(); I
!= E
; ++I
) {
745 NodeAddr
<UseNode
*> UseN
= *I
;
746 assert(!(UseN
.Addr
->getFlags() & NodeAttrs::PhiRef
) &&
747 "Found a PhiRef node as a real reached use!!");
749 NodeAddr
<StmtNode
*> OwnerN
= UseN
.Addr
->getOwner(*DFG
);
750 MachineInstr
*UseMI
= OwnerN
.Addr
->getCode();
751 LLVM_DEBUG(dbgs() << "\t\t[MI <" << printMBBReference(*UseMI
->getParent())
752 << ">]: " << *UseMI
<< "\n");
755 unsigned NumOperands
= UseMI
->getNumOperands();
756 for (unsigned j
= 0; j
< NumOperands
- 1; ++j
) {
757 const MachineOperand
&op
= UseMI
->getOperand(j
);
758 if (op
.isReg() && op
.isUse() && DefR
== op
.getReg())
761 // It is possible that the register will not be found in any operand.
762 // This could happen, for example, when DefR = R4, but the used
765 // Change UseMI if replacement is possible. If any replacement failed,
766 // or wasn't attempted, make sure to keep the TFR.
767 bool Xformed
= false;
768 if (UseMOnum
>= 0 && InstrEvalResult
[UseMI
])
769 Xformed
= xformUseMI(MI
, UseMI
, UseN
, UseMOnum
);
779 bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction
&MF
) {
780 if (skipFunction(MF
.getFunction()))
783 bool Changed
= false;
784 auto &HST
= MF
.getSubtarget
<HexagonSubtarget
>();
785 MRI
= &MF
.getRegInfo();
786 HII
= HST
.getInstrInfo();
787 HRI
= HST
.getRegisterInfo();
788 const auto &MDF
= getAnalysis
<MachineDominanceFrontier
>();
789 MDT
= &getAnalysis
<MachineDominatorTree
>();
790 const TargetOperandInfo
TOI(*HII
);
792 DataFlowGraph
G(MF
, *HII
, *HRI
, *MDT
, MDF
, TOI
);
793 // Need to keep dead phis because we can propagate uses of registers into
794 // nodes dominated by those would-be phis.
795 G
.build(BuildOptions::KeepDeadPhis
);
798 Liveness
L(*MRI
, *DFG
);
803 NodeAddr
<FuncNode
*> FA
= DFG
->getFunc();
804 LLVM_DEBUG(dbgs() << "==== [RefMap#]=====:\n "
805 << Print
<NodeAddr
<FuncNode
*>>(FA
, *DFG
) << "\n");
807 for (NodeAddr
<BlockNode
*> BA
: FA
.Addr
->members(*DFG
))
808 Changed
|= processBlock(BA
);
810 for (auto MI
: Deleted
)
811 MI
->eraseFromParent();
823 //===----------------------------------------------------------------------===//
824 // Public Constructor Functions
825 //===----------------------------------------------------------------------===//
827 FunctionPass
*llvm::createHexagonOptAddrMode() {
828 return new HexagonOptAddrMode();