LLVM 24.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"
24
25#define DEBUG_TYPE "hexagon-abs"
26
27using namespace llvm;
28
29STATISTIC(HexagonNumLoadAbsConversions,
30 "Number of Load instructions converted to absolute-set form");
31STATISTIC(HexagonNumStoreAbsConversions,
32 "Number of Store instructions converted to absolute-set form");
33
34namespace {
35
36class HexagonGenMemAbsolute : public MachineFunctionPass {
37 const HexagonInstrInfo *TII = nullptr;
38 MachineRegisterInfo *MRI = nullptr;
39
40public:
41 static char ID;
42 HexagonGenMemAbsolute() : MachineFunctionPass(ID) {}
43
44 StringRef getPassName() const override {
45 return "Hexagon Generate Load/Store Set Absolute Address Instruction";
46 }
47
48 void getAnalysisUsage(AnalysisUsage &AU) const override {
50 AU.addRequired<MachineDominatorTreeWrapperPass>();
51 AU.addPreserved<MachineDominatorTreeWrapperPass>();
52 }
53
54 bool runOnMachineFunction(MachineFunction &Fn) override;
55
56private:
57 static bool isValidIndexedLoad(int &Opcode, int &NewOpcode);
58 static bool isValidIndexedStore(int &Opcode, int &NewOpcode);
59};
60} // namespace
61
62char HexagonGenMemAbsolute::ID = 0;
63
64INITIALIZE_PASS(HexagonGenMemAbsolute, "hexagon-gen-load-absolute",
65 "Hexagon Generate Load/Store Set Absolute Address Instruction",
66 false, false)
67
68bool HexagonGenMemAbsolute::runOnMachineFunction(MachineFunction &Fn) {
69 if (skipFunction(Fn.getFunction()))
70 return false;
71
72 TII = Fn.getSubtarget<HexagonSubtarget>().getInstrInfo();
73 MRI = &Fn.getRegInfo();
74
76 getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
77
78 // Loop over all of the basic blocks
79 for (MachineBasicBlock &MBB : Fn) {
80 // Traverse the basic block
81 for (MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end();
82 ++MII) {
83 MachineInstr *MI = &*MII;
84 int Opc = MI->getOpcode();
85 if (Opc != Hexagon::CONST32 && Opc != Hexagon::A2_tfrsi)
86 continue;
87
88 const MachineOperand &MO = MI->getOperand(0);
89 if (!MO.isReg() || !MO.isDef())
90 continue;
91
92 unsigned DstReg = MO.getReg();
93 if (MRI->use_nodbg_empty(DstReg))
94 continue;
95
96 typedef MachineRegisterInfo::use_nodbg_iterator use_iterator;
97 use_iterator NextUseMI = MRI->use_nodbg_begin(DstReg);
98
99 MachineInstr *NextMI = NextUseMI->getParent();
100 int NextOpc = NextMI->getOpcode();
101 int NewOpc;
102 bool IsLoad = isValidIndexedLoad(NextOpc, NewOpc);
103
104 if (!IsLoad && !isValidIndexedStore(NextOpc, NewOpc))
105 continue;
106
107 // Base and Offset positions for load and store instructions
108 // Load R(dest), R(base), Imm -> R(dest) = mem(R(base) + Imm)
109 // Store R(base), Imm, R (src) -> mem(R(base) + Imm) = R(src)
110 unsigned BaseRegPos, ImmPos, RegPos;
111 if (!TII->getBaseAndOffsetPosition(*NextMI, BaseRegPos, ImmPos))
112 continue;
113 RegPos = IsLoad ? 0 : 2;
114
115 bool IsGlobal = MI->getOperand(1).isGlobal();
116 if (!MI->getOperand(1).isImm() && !IsGlobal)
117 continue;
118
119 const MachineOperand *BaseOp = nullptr;
120 int64_t Offset;
121 bool Scalable;
122 TII->getMemOperandWithOffset(*NextMI, BaseOp, Offset, Scalable);
123
124 // Ensure BaseOp is non-null and register type.
125 if (!BaseOp || !BaseOp->isReg())
126 continue;
127
128 if (Scalable)
129 continue;
130
131 unsigned BaseReg = BaseOp->getReg();
132 if ((DstReg != BaseReg) || (Offset != 0))
133 continue;
134
135 const MachineOperand &MO0 = NextMI->getOperand(RegPos);
136
137 if (!MO0.isReg())
138 continue;
139
140 unsigned LoadStoreReg = MO0.getReg();
141
142 // Store: Bail out if the src and base are same (def and use on same
143 // register).
144 if (LoadStoreReg == BaseReg)
145 continue;
146
147 // Insert the absolute-set instruction "I" only if the use of the
148 // BaseReg in "I" dominates the rest of the uses of BaseReg and if
149 // there are more than 2 uses of this BaseReg.
150 bool Dominates = true;
151 unsigned Counter = 0;
152 for (use_iterator I = NextUseMI, E = MRI->use_nodbg_end(); I != E; ++I) {
153 Counter++;
154 if (!MDT.dominates(NextMI, I->getParent()))
155 Dominates = false;
156 }
157
158 if ((!Dominates) || (Counter < 3))
159 continue;
160
161 // If we reach here, we have met all the conditions required for the
162 // replacement of the absolute instruction.
163 LLVM_DEBUG({
164 dbgs() << "Found a pair of instructions for absolute-set "
165 << (IsLoad ? "load" : "store") << "\n";
166 dbgs() << *MI;
167 dbgs() << *NextMI;
168 });
169 MachineBasicBlock *ParentBlock = NextMI->getParent();
171 if (IsLoad) { // Insert absolute-set load instruction
172 ++HexagonNumLoadAbsConversions;
173 MIB = BuildMI(*ParentBlock, NextMI, NextMI->getDebugLoc(),
174 TII->get(NewOpc), LoadStoreReg)
175 .addReg(DstReg, RegState::Define);
176 } else { // Insert absolute-set store instruction
177 ++HexagonNumStoreAbsConversions;
178 MIB = BuildMI(*ParentBlock, NextMI, NextMI->getDebugLoc(),
179 TII->get(NewOpc), DstReg);
180 }
181
182 MachineOperand ImmOperand = MI->getOperand(1);
183 if (IsGlobal)
184 MIB.addGlobalAddress(ImmOperand.getGlobal(), ImmOperand.getOffset(),
185 ImmOperand.getTargetFlags());
186 else
187 MIB.addImm(ImmOperand.getImm());
188
189 if (IsLoad)
190 MIB->getOperand(0).setSubReg(MO0.getSubReg());
191 else
192 MIB.addReg(LoadStoreReg, {}, MO0.getSubReg());
193
194 LLVM_DEBUG(dbgs() << "Replaced with " << *MIB << "\n");
195 // Erase the instructions that got replaced.
196 MII = MBB.erase(MI);
197 --MII;
198 NextMI->getParent()->erase(NextMI);
199 }
200 }
201
202 return true;
203}
204
205bool HexagonGenMemAbsolute::isValidIndexedLoad(int &Opc, int &NewOpc) {
206
207 bool Result = true;
208 switch (Opc) {
209 case Hexagon::L2_loadrb_io:
210 NewOpc = Hexagon::L4_loadrb_ap;
211 break;
212 case Hexagon::L2_loadrh_io:
213 NewOpc = Hexagon::L4_loadrh_ap;
214 break;
215 case Hexagon::L2_loadri_io:
216 NewOpc = Hexagon::L4_loadri_ap;
217 break;
218 case Hexagon::L2_loadrd_io:
219 NewOpc = Hexagon::L4_loadrd_ap;
220 break;
221 case Hexagon::L2_loadruh_io:
222 NewOpc = Hexagon::L4_loadruh_ap;
223 break;
224 case Hexagon::L2_loadrub_io:
225 NewOpc = Hexagon::L4_loadrub_ap;
226 break;
227 default:
228 Result = false;
229 }
230
231 return Result;
232}
233
234bool HexagonGenMemAbsolute::isValidIndexedStore(int &Opc, int &NewOpc) {
235
236 bool Result = true;
237 switch (Opc) {
238 case Hexagon::S2_storerd_io:
239 NewOpc = Hexagon::S4_storerd_ap;
240 break;
241 case Hexagon::S2_storeri_io:
242 NewOpc = Hexagon::S4_storeri_ap;
243 break;
244 case Hexagon::S2_storerh_io:
245 NewOpc = Hexagon::S4_storerh_ap;
246 break;
247 case Hexagon::S2_storerb_io:
248 NewOpc = Hexagon::S4_storerb_ap;
249 break;
250 default:
251 Result = false;
252 }
253
254 return Result;
255}
256
257//===----------------------------------------------------------------------===//
258// Public Constructor Functions
259//===----------------------------------------------------------------------===//
260
262 return new HexagonGenMemAbsolute();
263}
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
static bool isValidIndexedLoad(const LoadSDNode *LD)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
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:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
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:314
const HexagonInstrInfo * getInstrInfo() const override
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
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.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_iterator< true, false, true, true, false > use_nodbg_iterator
use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the specified register,...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Define
Register definition.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
FunctionPass * createHexagonGenMemAbsolute()