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"
24 #include "llvm/Target/TargetMachine.h"
26 #define DEBUG_TYPE "hexagon-abs"
30 STATISTIC(HexagonNumLoadAbsConversions
,
31 "Number of Load instructions converted to absolute-set form");
32 STATISTIC(HexagonNumStoreAbsConversions
,
33 "Number of Store instructions converted to absolute-set form");
36 FunctionPass
*createHexagonGenMemAbsolute();
37 void initializeHexagonGenMemAbsolutePass(PassRegistry
&Registry
);
42 class HexagonGenMemAbsolute
: public MachineFunctionPass
{
43 const HexagonInstrInfo
*TII
;
44 MachineRegisterInfo
*MRI
;
45 const TargetRegisterInfo
*TRI
;
49 HexagonGenMemAbsolute() : MachineFunctionPass(ID
), TII(0), MRI(0), TRI(0) {
50 initializeHexagonGenMemAbsolutePass(*PassRegistry::getPassRegistry());
53 StringRef
getPassName() const override
{
54 return "Hexagon Generate Load/Store Set Absolute Address Instruction";
57 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
58 MachineFunctionPass::getAnalysisUsage(AU
);
59 AU
.addRequired
<MachineDominatorTreeWrapperPass
>();
60 AU
.addPreserved
<MachineDominatorTreeWrapperPass
>();
63 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
66 static bool isValidIndexedLoad(int &Opcode
, int &NewOpcode
);
67 static bool isValidIndexedStore(int &Opcode
, int &NewOpcode
);
71 char HexagonGenMemAbsolute::ID
= 0;
73 INITIALIZE_PASS(HexagonGenMemAbsolute
, "hexagon-gen-load-absolute",
74 "Hexagon Generate Load/Store Set Absolute Address Instruction",
77 bool HexagonGenMemAbsolute::runOnMachineFunction(MachineFunction
&Fn
) {
78 if (skipFunction(Fn
.getFunction()))
81 TII
= Fn
.getSubtarget
<HexagonSubtarget
>().getInstrInfo();
82 MRI
= &Fn
.getRegInfo();
83 TRI
= Fn
.getRegInfo().getTargetRegisterInfo();
85 MachineDominatorTree
&MDT
=
86 getAnalysis
<MachineDominatorTreeWrapperPass
>().getDomTree();
88 // Loop over all of the basic blocks
89 for (MachineFunction::iterator MBBb
= Fn
.begin(), MBBe
= Fn
.end();
90 MBBb
!= MBBe
; ++MBBb
) {
91 MachineBasicBlock
*MBB
= &*MBBb
;
92 // Traverse the basic block
93 for (MachineBasicBlock::iterator MII
= MBB
->begin(); MII
!= MBB
->end();
95 MachineInstr
*MI
= &*MII
;
96 int Opc
= MI
->getOpcode();
97 if (Opc
!= Hexagon::CONST32
&& Opc
!= Hexagon::A2_tfrsi
)
100 const MachineOperand
&MO
= MI
->getOperand(0);
101 if (!MO
.isReg() || !MO
.isDef())
104 unsigned DstReg
= MO
.getReg();
105 if (MRI
->use_nodbg_empty(DstReg
))
108 typedef MachineRegisterInfo::use_nodbg_iterator use_iterator
;
109 use_iterator NextUseMI
= MRI
->use_nodbg_begin(DstReg
);
111 MachineInstr
*NextMI
= NextUseMI
->getParent();
112 int NextOpc
= NextMI
->getOpcode();
114 bool IsLoad
= isValidIndexedLoad(NextOpc
, NewOpc
);
116 if (!IsLoad
&& !isValidIndexedStore(NextOpc
, NewOpc
))
119 // Base and Offset positions for load and store instructions
120 // Load R(dest), R(base), Imm -> R(dest) = mem(R(base) + Imm)
121 // Store R(base), Imm, R (src) -> mem(R(base) + Imm) = R(src)
122 unsigned BaseRegPos
, ImmPos
, RegPos
;
123 if (!TII
->getBaseAndOffsetPosition(*NextMI
, BaseRegPos
, ImmPos
))
125 RegPos
= IsLoad
? 0 : 2;
127 bool IsGlobal
= MI
->getOperand(1).isGlobal();
128 if (!MI
->getOperand(1).isImm() && !IsGlobal
)
131 const MachineOperand
*BaseOp
= nullptr;
134 TII
->getMemOperandWithOffset(*NextMI
, BaseOp
, Offset
, Scalable
, TRI
);
136 // Ensure BaseOp is non-null and register type.
137 if (!BaseOp
|| !BaseOp
->isReg())
143 unsigned BaseReg
= BaseOp
->getReg();
144 if ((DstReg
!= BaseReg
) || (Offset
!= 0))
147 const MachineOperand
&MO0
= NextMI
->getOperand(RegPos
);
152 unsigned LoadStoreReg
= MO0
.getReg();
154 // Store: Bail out if the src and base are same (def and use on same
156 if (LoadStoreReg
== BaseReg
)
159 // Insert the absolute-set instruction "I" only if the use of the
160 // BaseReg in "I" dominates the rest of the uses of BaseReg and if
161 // there are more than 2 uses of this BaseReg.
162 bool Dominates
= true;
163 unsigned Counter
= 0;
164 for (use_iterator I
= NextUseMI
, E
= MRI
->use_nodbg_end(); I
!= E
; ++I
) {
166 if (!MDT
.dominates(NextMI
, I
->getParent()))
170 if ((!Dominates
) || (Counter
< 3))
173 // If we reach here, we have met all the conditions required for the
174 // replacement of the absolute instruction.
176 dbgs() << "Found a pair of instructions for absolute-set "
177 << (IsLoad
? "load" : "store") << "\n";
181 MachineBasicBlock
*ParentBlock
= NextMI
->getParent();
182 MachineInstrBuilder MIB
;
183 if (IsLoad
) { // Insert absolute-set load instruction
184 ++HexagonNumLoadAbsConversions
;
185 MIB
= BuildMI(*ParentBlock
, NextMI
, NextMI
->getDebugLoc(),
186 TII
->get(NewOpc
), LoadStoreReg
)
187 .addReg(DstReg
, RegState::Define
);
188 } else { // Insert absolute-set store instruction
189 ++HexagonNumStoreAbsConversions
;
190 MIB
= BuildMI(*ParentBlock
, NextMI
, NextMI
->getDebugLoc(),
191 TII
->get(NewOpc
), DstReg
);
194 MachineOperand ImmOperand
= MI
->getOperand(1);
196 MIB
.addGlobalAddress(ImmOperand
.getGlobal(), ImmOperand
.getOffset(),
197 ImmOperand
.getTargetFlags());
199 MIB
.addImm(ImmOperand
.getImm());
202 MIB
->getOperand(0).setSubReg(MO0
.getSubReg());
204 MIB
.addReg(LoadStoreReg
, 0, MO0
.getSubReg());
206 LLVM_DEBUG(dbgs() << "Replaced with " << *MIB
<< "\n");
207 // Erase the instructions that got replaced.
208 MII
= MBB
->erase(MI
);
210 NextMI
->getParent()->erase(NextMI
);
217 bool HexagonGenMemAbsolute::isValidIndexedLoad(int &Opc
, int &NewOpc
) {
221 case Hexagon::L2_loadrb_io
:
222 NewOpc
= Hexagon::L4_loadrb_ap
;
224 case Hexagon::L2_loadrh_io
:
225 NewOpc
= Hexagon::L4_loadrh_ap
;
227 case Hexagon::L2_loadri_io
:
228 NewOpc
= Hexagon::L4_loadri_ap
;
230 case Hexagon::L2_loadrd_io
:
231 NewOpc
= Hexagon::L4_loadrd_ap
;
233 case Hexagon::L2_loadruh_io
:
234 NewOpc
= Hexagon::L4_loadruh_ap
;
236 case Hexagon::L2_loadrub_io
:
237 NewOpc
= Hexagon::L4_loadrub_ap
;
246 bool HexagonGenMemAbsolute::isValidIndexedStore(int &Opc
, int &NewOpc
) {
250 case Hexagon::S2_storerd_io
:
251 NewOpc
= Hexagon::S4_storerd_ap
;
253 case Hexagon::S2_storeri_io
:
254 NewOpc
= Hexagon::S4_storeri_ap
;
256 case Hexagon::S2_storerh_io
:
257 NewOpc
= Hexagon::S4_storerh_ap
;
259 case Hexagon::S2_storerb_io
:
260 NewOpc
= Hexagon::S4_storerb_ap
;
269 //===----------------------------------------------------------------------===//
270 // Public Constructor Functions
271 //===----------------------------------------------------------------------===//
273 FunctionPass
*llvm::createHexagonGenMemAbsolute() {
274 return new HexagonGenMemAbsolute();