LLVM 19.0.0git
HexagonGenMemAbsolute.cpp
Go to the documentation of this file.
1//===--- HexagonGenMemAbsolute.cpp - Generate Load/Store Set Absolute ---===//
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
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.
13
15#include "llvm/ADT/Statistic.h"
20#include "llvm/CodeGen/Passes.h"
22#include "llvm/Support/Debug.h"
25
26#define DEBUG_TYPE "hexagon-abs"
27
28using namespace llvm;
29
30STATISTIC(HexagonNumLoadAbsConversions,
31 "Number of Load instructions converted to absolute-set form");
32STATISTIC(HexagonNumStoreAbsConversions,
33 "Number of Store instructions converted to absolute-set form");
34
35namespace llvm {
38} // namespace llvm
39
40namespace {
41
42class HexagonGenMemAbsolute : public MachineFunctionPass {
43 const HexagonInstrInfo *TII;
46
47public:
48 static char ID;
49 HexagonGenMemAbsolute() : MachineFunctionPass(ID), TII(0), MRI(0), TRI(0) {
51 }
52
53 StringRef getPassName() const override {
54 return "Hexagon Generate Load/Store Set Absolute Address Instruction";
55 }
56
57 void getAnalysisUsage(AnalysisUsage &AU) const override {
61 }
62
63 bool runOnMachineFunction(MachineFunction &Fn) override;
64
65private:
66 static bool isValidIndexedLoad(int &Opcode, int &NewOpcode);
67 static bool isValidIndexedStore(int &Opcode, int &NewOpcode);
68};
69} // namespace
70
71char HexagonGenMemAbsolute::ID = 0;
72
73INITIALIZE_PASS(HexagonGenMemAbsolute, "hexagon-gen-load-absolute",
74 "Hexagon Generate Load/Store Set Absolute Address Instruction",
75 false, false)
76
77bool HexagonGenMemAbsolute::runOnMachineFunction(MachineFunction &Fn) {
78 if (skipFunction(Fn.getFunction()))
79 return false;
80
81 TII = Fn.getSubtarget<HexagonSubtarget>().getInstrInfo();
82 MRI = &Fn.getRegInfo();
83 TRI = Fn.getRegInfo().getTargetRegisterInfo();
84
85 MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
86
87 // Loop over all of the basic blocks
88 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
89 MBBb != MBBe; ++MBBb) {
90 MachineBasicBlock *MBB = &*MBBb;
91 // Traverse the basic block
92 for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
93 ++MII) {
94 MachineInstr *MI = &*MII;
95 int Opc = MI->getOpcode();
96 if (Opc != Hexagon::CONST32 && Opc != Hexagon::A2_tfrsi)
97 continue;
98
99 const MachineOperand &MO = MI->getOperand(0);
100 if (!MO.isReg() || !MO.isDef())
101 continue;
102
103 unsigned DstReg = MO.getReg();
104 if (MRI->use_nodbg_empty(DstReg))
105 continue;
106
107 typedef MachineRegisterInfo::use_nodbg_iterator use_iterator;
108 use_iterator NextUseMI = MRI->use_nodbg_begin(DstReg);
109
110 MachineInstr *NextMI = NextUseMI->getParent();
111 int NextOpc = NextMI->getOpcode();
112 int NewOpc;
113 bool IsLoad = isValidIndexedLoad(NextOpc, NewOpc);
114
115 if (!IsLoad && !isValidIndexedStore(NextOpc, NewOpc))
116 continue;
117
118 // Base and Offset positions for load and store instructions
119 // Load R(dest), R(base), Imm -> R(dest) = mem(R(base) + Imm)
120 // Store R(base), Imm, R (src) -> mem(R(base) + Imm) = R(src)
121 unsigned BaseRegPos, ImmPos, RegPos;
122 if (!TII->getBaseAndOffsetPosition(*NextMI, BaseRegPos, ImmPos))
123 continue;
124 RegPos = IsLoad ? 0 : 2;
125
126 bool IsGlobal = MI->getOperand(1).isGlobal();
127 if (!MI->getOperand(1).isImm() && !IsGlobal)
128 continue;
129
130 const MachineOperand *BaseOp = nullptr;
131 int64_t Offset;
132 bool Scalable;
133 TII->getMemOperandWithOffset(*NextMI, BaseOp, Offset, Scalable, TRI);
134
135 // Ensure BaseOp is non-null and register type.
136 if (!BaseOp || !BaseOp->isReg())
137 continue;
138
139 if (Scalable)
140 continue;
141
142 unsigned BaseReg = BaseOp->getReg();
143 if ((DstReg != BaseReg) || (Offset != 0))
144 continue;
145
146 const MachineOperand &MO0 = NextMI->getOperand(RegPos);
147
148 if (!MO0.isReg())
149 continue;
150
151 unsigned LoadStoreReg = MO0.getReg();
152
153 // Store: Bail out if the src and base are same (def and use on same
154 // register).
155 if (LoadStoreReg == BaseReg)
156 continue;
157
158 // Insert the absolute-set instruction "I" only if the use of the
159 // BaseReg in "I" dominates the rest of the uses of BaseReg and if
160 // there are more than 2 uses of this BaseReg.
161 bool Dominates = true;
162 unsigned Counter = 0;
163 for (use_iterator I = NextUseMI, E = MRI->use_nodbg_end(); I != E; ++I) {
164 Counter++;
165 if (!MDT.dominates(NextMI, I->getParent()))
166 Dominates = false;
167 }
168
169 if ((!Dominates) || (Counter < 3))
170 continue;
171
172 // If we reach here, we have met all the conditions required for the
173 // replacement of the absolute instruction.
174 LLVM_DEBUG({
175 dbgs() << "Found a pair of instructions for absolute-set "
176 << (IsLoad ? "load" : "store") << "\n";
177 dbgs() << *MI;
178 dbgs() << *NextMI;
179 });
180 MachineBasicBlock *ParentBlock = NextMI->getParent();
182 if (IsLoad) { // Insert absolute-set load instruction
183 ++HexagonNumLoadAbsConversions;
184 MIB = BuildMI(*ParentBlock, NextMI, NextMI->getDebugLoc(),
185 TII->get(NewOpc), LoadStoreReg)
186 .addReg(DstReg, RegState::Define);
187 } else { // Insert absolute-set store instruction
188 ++HexagonNumStoreAbsConversions;
189 MIB = BuildMI(*ParentBlock, NextMI, NextMI->getDebugLoc(),
190 TII->get(NewOpc), DstReg);
191 }
192
193 MachineOperand ImmOperand = MI->getOperand(1);
194 if (IsGlobal)
195 MIB.addGlobalAddress(ImmOperand.getGlobal(), ImmOperand.getOffset(),
196 ImmOperand.getTargetFlags());
197 else
198 MIB.addImm(ImmOperand.getImm());
199
200 if (IsLoad)
201 MIB->getOperand(0).setSubReg(MO0.getSubReg());
202 else
203 MIB.addReg(LoadStoreReg, 0, MO0.getSubReg());
204
205 LLVM_DEBUG(dbgs() << "Replaced with " << *MIB << "\n");
206 // Erase the instructions that got replaced.
207 MII = MBB->erase(MI);
208 --MII;
209 NextMI->getParent()->erase(NextMI);
210 }
211 }
212
213 return true;
214}
215
216bool HexagonGenMemAbsolute::isValidIndexedLoad(int &Opc, int &NewOpc) {
217
218 bool Result = true;
219 switch (Opc) {
220 case Hexagon::L2_loadrb_io:
221 NewOpc = Hexagon::L4_loadrb_ap;
222 break;
223 case Hexagon::L2_loadrh_io:
224 NewOpc = Hexagon::L4_loadrh_ap;
225 break;
226 case Hexagon::L2_loadri_io:
227 NewOpc = Hexagon::L4_loadri_ap;
228 break;
229 case Hexagon::L2_loadrd_io:
230 NewOpc = Hexagon::L4_loadrd_ap;
231 break;
232 case Hexagon::L2_loadruh_io:
233 NewOpc = Hexagon::L4_loadruh_ap;
234 break;
235 case Hexagon::L2_loadrub_io:
236 NewOpc = Hexagon::L4_loadrub_ap;
237 break;
238 default:
239 Result = false;
240 }
241
242 return Result;
243}
244
245bool HexagonGenMemAbsolute::isValidIndexedStore(int &Opc, int &NewOpc) {
246
247 bool Result = true;
248 switch (Opc) {
249 case Hexagon::S2_storerd_io:
250 NewOpc = Hexagon::S4_storerd_ap;
251 break;
252 case Hexagon::S2_storeri_io:
253 NewOpc = Hexagon::S4_storeri_ap;
254 break;
255 case Hexagon::S2_storerh_io:
256 NewOpc = Hexagon::S4_storerh_ap;
257 break;
258 case Hexagon::S2_storerb_io:
259 NewOpc = Hexagon::S4_storerb_ap;
260 break;
261 default:
262 Result = false;
263 }
264
265 return Result;
266}
267
268//===----------------------------------------------------------------------===//
269// Public Constructor Functions
270//===----------------------------------------------------------------------===//
271
273 return new HexagonGenMemAbsolute();
274}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
#define LLVM_DEBUG(X)
Definition: Debug.h:101
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
static bool isValidIndexedLoad(const LoadSDNode *LD)
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos, unsigned &OffsetPos) const override
For instructions with a base and offset, return the position of the base register and offset operands...
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:558
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:341
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:487
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:568
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
unsigned getTargetFlags() const
Register getReg() const
getReg - Returns the register number.
int64_t getOffset() const
Return the offset from the symbol in this operand.
reg_begin/reg_end - Provide iteration support to walk over all definitions and uses of a register wit...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:37
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
A global registry used in conjunction with static constructors to make pluggable components (like tar...
Definition: Registry.h:44
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ Define
Register definition.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void initializeHexagonGenMemAbsolutePass(PassRegistry &Registry)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
FunctionPass * createHexagonGenMemAbsolute()