1 //===--- HexagonGenMemAbsolute.cpp - Generate Load/Store Set Absolute ---===//
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 //===----------------------------------------------------------------------===//
9 // This pass traverses through all the basic blocks in a function and converts
10 // an indexed load/store with offset "0" to a absolute-set load/store
11 // instruction as long as the use of the register in the new instruction
12 // dominates the rest of the uses and there are more than 2 uses.
14 #include "HexagonTargetMachine.h"
15 #include "llvm/ADT/Statistic.h"
16 #include "llvm/CodeGen/MachineDominators.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/Passes.h"
21 #include "llvm/CodeGen/TargetInstrInfo.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
25 #define DEBUG_TYPE "hexagon-abs"
29 STATISTIC(HexagonNumLoadAbsConversions
,
30 "Number of Load instructions converted to absolute-set form");
31 STATISTIC(HexagonNumStoreAbsConversions
,
32 "Number of Store instructions converted to absolute-set form");
35 FunctionPass
*createHexagonGenMemAbsolute();
36 void initializeHexagonGenMemAbsolutePass(PassRegistry
&Registry
);
41 class HexagonGenMemAbsolute
: public MachineFunctionPass
{
42 const HexagonInstrInfo
*TII
;
43 MachineRegisterInfo
*MRI
;
44 const TargetRegisterInfo
*TRI
;
48 HexagonGenMemAbsolute() : MachineFunctionPass(ID
), TII(0), MRI(0), TRI(0) {
49 initializeHexagonGenMemAbsolutePass(*PassRegistry::getPassRegistry());
52 StringRef
getPassName() const override
{
53 return "Hexagon Generate Load/Store Set Absolute Address Instruction";
56 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
57 MachineFunctionPass::getAnalysisUsage(AU
);
58 AU
.addRequired
<MachineDominatorTreeWrapperPass
>();
59 AU
.addPreserved
<MachineDominatorTreeWrapperPass
>();
62 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
65 static bool isValidIndexedLoad(int &Opcode
, int &NewOpcode
);
66 static bool isValidIndexedStore(int &Opcode
, int &NewOpcode
);
70 char HexagonGenMemAbsolute::ID
= 0;
72 INITIALIZE_PASS(HexagonGenMemAbsolute
, "hexagon-gen-load-absolute",
73 "Hexagon Generate Load/Store Set Absolute Address Instruction",
76 bool HexagonGenMemAbsolute::runOnMachineFunction(MachineFunction
&Fn
) {
77 if (skipFunction(Fn
.getFunction()))
80 TII
= Fn
.getSubtarget
<HexagonSubtarget
>().getInstrInfo();
81 MRI
= &Fn
.getRegInfo();
82 TRI
= Fn
.getRegInfo().getTargetRegisterInfo();
84 MachineDominatorTree
&MDT
=
85 getAnalysis
<MachineDominatorTreeWrapperPass
>().getDomTree();
87 // Loop over all of the basic blocks
88 for (MachineBasicBlock
&MBB
: Fn
) {
89 // Traverse the basic block
90 for (MachineBasicBlock::iterator MII
= MBB
.begin(); MII
!= MBB
.end();
92 MachineInstr
*MI
= &*MII
;
93 int Opc
= MI
->getOpcode();
94 if (Opc
!= Hexagon::CONST32
&& Opc
!= Hexagon::A2_tfrsi
)
97 const MachineOperand
&MO
= MI
->getOperand(0);
98 if (!MO
.isReg() || !MO
.isDef())
101 unsigned DstReg
= MO
.getReg();
102 if (MRI
->use_nodbg_empty(DstReg
))
105 typedef MachineRegisterInfo::use_nodbg_iterator use_iterator
;
106 use_iterator NextUseMI
= MRI
->use_nodbg_begin(DstReg
);
108 MachineInstr
*NextMI
= NextUseMI
->getParent();
109 int NextOpc
= NextMI
->getOpcode();
111 bool IsLoad
= isValidIndexedLoad(NextOpc
, NewOpc
);
113 if (!IsLoad
&& !isValidIndexedStore(NextOpc
, NewOpc
))
116 // Base and Offset positions for load and store instructions
117 // Load R(dest), R(base), Imm -> R(dest) = mem(R(base) + Imm)
118 // Store R(base), Imm, R (src) -> mem(R(base) + Imm) = R(src)
119 unsigned BaseRegPos
, ImmPos
, RegPos
;
120 if (!TII
->getBaseAndOffsetPosition(*NextMI
, BaseRegPos
, ImmPos
))
122 RegPos
= IsLoad
? 0 : 2;
124 bool IsGlobal
= MI
->getOperand(1).isGlobal();
125 if (!MI
->getOperand(1).isImm() && !IsGlobal
)
128 const MachineOperand
*BaseOp
= nullptr;
131 TII
->getMemOperandWithOffset(*NextMI
, BaseOp
, Offset
, Scalable
, TRI
);
133 // Ensure BaseOp is non-null and register type.
134 if (!BaseOp
|| !BaseOp
->isReg())
140 unsigned BaseReg
= BaseOp
->getReg();
141 if ((DstReg
!= BaseReg
) || (Offset
!= 0))
144 const MachineOperand
&MO0
= NextMI
->getOperand(RegPos
);
149 unsigned LoadStoreReg
= MO0
.getReg();
151 // Store: Bail out if the src and base are same (def and use on same
153 if (LoadStoreReg
== BaseReg
)
156 // Insert the absolute-set instruction "I" only if the use of the
157 // BaseReg in "I" dominates the rest of the uses of BaseReg and if
158 // there are more than 2 uses of this BaseReg.
159 bool Dominates
= true;
160 unsigned Counter
= 0;
161 for (use_iterator I
= NextUseMI
, E
= MRI
->use_nodbg_end(); I
!= E
; ++I
) {
163 if (!MDT
.dominates(NextMI
, I
->getParent()))
167 if ((!Dominates
) || (Counter
< 3))
170 // If we reach here, we have met all the conditions required for the
171 // replacement of the absolute instruction.
173 dbgs() << "Found a pair of instructions for absolute-set "
174 << (IsLoad
? "load" : "store") << "\n";
178 MachineBasicBlock
*ParentBlock
= NextMI
->getParent();
179 MachineInstrBuilder MIB
;
180 if (IsLoad
) { // Insert absolute-set load instruction
181 ++HexagonNumLoadAbsConversions
;
182 MIB
= BuildMI(*ParentBlock
, NextMI
, NextMI
->getDebugLoc(),
183 TII
->get(NewOpc
), LoadStoreReg
)
184 .addReg(DstReg
, RegState::Define
);
185 } else { // Insert absolute-set store instruction
186 ++HexagonNumStoreAbsConversions
;
187 MIB
= BuildMI(*ParentBlock
, NextMI
, NextMI
->getDebugLoc(),
188 TII
->get(NewOpc
), DstReg
);
191 MachineOperand ImmOperand
= MI
->getOperand(1);
193 MIB
.addGlobalAddress(ImmOperand
.getGlobal(), ImmOperand
.getOffset(),
194 ImmOperand
.getTargetFlags());
196 MIB
.addImm(ImmOperand
.getImm());
199 MIB
->getOperand(0).setSubReg(MO0
.getSubReg());
201 MIB
.addReg(LoadStoreReg
, 0, MO0
.getSubReg());
203 LLVM_DEBUG(dbgs() << "Replaced with " << *MIB
<< "\n");
204 // Erase the instructions that got replaced.
207 NextMI
->getParent()->erase(NextMI
);
214 bool HexagonGenMemAbsolute::isValidIndexedLoad(int &Opc
, int &NewOpc
) {
218 case Hexagon::L2_loadrb_io
:
219 NewOpc
= Hexagon::L4_loadrb_ap
;
221 case Hexagon::L2_loadrh_io
:
222 NewOpc
= Hexagon::L4_loadrh_ap
;
224 case Hexagon::L2_loadri_io
:
225 NewOpc
= Hexagon::L4_loadri_ap
;
227 case Hexagon::L2_loadrd_io
:
228 NewOpc
= Hexagon::L4_loadrd_ap
;
230 case Hexagon::L2_loadruh_io
:
231 NewOpc
= Hexagon::L4_loadruh_ap
;
233 case Hexagon::L2_loadrub_io
:
234 NewOpc
= Hexagon::L4_loadrub_ap
;
243 bool HexagonGenMemAbsolute::isValidIndexedStore(int &Opc
, int &NewOpc
) {
247 case Hexagon::S2_storerd_io
:
248 NewOpc
= Hexagon::S4_storerd_ap
;
250 case Hexagon::S2_storeri_io
:
251 NewOpc
= Hexagon::S4_storeri_ap
;
253 case Hexagon::S2_storerh_io
:
254 NewOpc
= Hexagon::S4_storerh_ap
;
256 case Hexagon::S2_storerb_io
:
257 NewOpc
= Hexagon::S4_storerb_ap
;
266 //===----------------------------------------------------------------------===//
267 // Public Constructor Functions
268 //===----------------------------------------------------------------------===//
270 FunctionPass
*llvm::createHexagonGenMemAbsolute() {
271 return new HexagonGenMemAbsolute();