Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonGenMemAbsolute.cpp
35268 views
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
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"
25
26
#define DEBUG_TYPE "hexagon-abs"
27
28
using namespace llvm;
29
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");
34
35
namespace llvm {
36
FunctionPass *createHexagonGenMemAbsolute();
37
void initializeHexagonGenMemAbsolutePass(PassRegistry &Registry);
38
} // namespace llvm
39
40
namespace {
41
42
class HexagonGenMemAbsolute : public MachineFunctionPass {
43
const HexagonInstrInfo *TII;
44
MachineRegisterInfo *MRI;
45
const TargetRegisterInfo *TRI;
46
47
public:
48
static char ID;
49
HexagonGenMemAbsolute() : MachineFunctionPass(ID), TII(0), MRI(0), TRI(0) {
50
initializeHexagonGenMemAbsolutePass(*PassRegistry::getPassRegistry());
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 {
58
MachineFunctionPass::getAnalysisUsage(AU);
59
AU.addRequired<MachineDominatorTreeWrapperPass>();
60
AU.addPreserved<MachineDominatorTreeWrapperPass>();
61
}
62
63
bool runOnMachineFunction(MachineFunction &Fn) override;
64
65
private:
66
static bool isValidIndexedLoad(int &Opcode, int &NewOpcode);
67
static bool isValidIndexedStore(int &Opcode, int &NewOpcode);
68
};
69
} // namespace
70
71
char HexagonGenMemAbsolute::ID = 0;
72
73
INITIALIZE_PASS(HexagonGenMemAbsolute, "hexagon-gen-load-absolute",
74
"Hexagon Generate Load/Store Set Absolute Address Instruction",
75
false, false)
76
77
bool 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 =
86
getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
87
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();
94
++MII) {
95
MachineInstr *MI = &*MII;
96
int Opc = MI->getOpcode();
97
if (Opc != Hexagon::CONST32 && Opc != Hexagon::A2_tfrsi)
98
continue;
99
100
const MachineOperand &MO = MI->getOperand(0);
101
if (!MO.isReg() || !MO.isDef())
102
continue;
103
104
unsigned DstReg = MO.getReg();
105
if (MRI->use_nodbg_empty(DstReg))
106
continue;
107
108
typedef MachineRegisterInfo::use_nodbg_iterator use_iterator;
109
use_iterator NextUseMI = MRI->use_nodbg_begin(DstReg);
110
111
MachineInstr *NextMI = NextUseMI->getParent();
112
int NextOpc = NextMI->getOpcode();
113
int NewOpc;
114
bool IsLoad = isValidIndexedLoad(NextOpc, NewOpc);
115
116
if (!IsLoad && !isValidIndexedStore(NextOpc, NewOpc))
117
continue;
118
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))
124
continue;
125
RegPos = IsLoad ? 0 : 2;
126
127
bool IsGlobal = MI->getOperand(1).isGlobal();
128
if (!MI->getOperand(1).isImm() && !IsGlobal)
129
continue;
130
131
const MachineOperand *BaseOp = nullptr;
132
int64_t Offset;
133
bool Scalable;
134
TII->getMemOperandWithOffset(*NextMI, BaseOp, Offset, Scalable, TRI);
135
136
// Ensure BaseOp is non-null and register type.
137
if (!BaseOp || !BaseOp->isReg())
138
continue;
139
140
if (Scalable)
141
continue;
142
143
unsigned BaseReg = BaseOp->getReg();
144
if ((DstReg != BaseReg) || (Offset != 0))
145
continue;
146
147
const MachineOperand &MO0 = NextMI->getOperand(RegPos);
148
149
if (!MO0.isReg())
150
continue;
151
152
unsigned LoadStoreReg = MO0.getReg();
153
154
// Store: Bail out if the src and base are same (def and use on same
155
// register).
156
if (LoadStoreReg == BaseReg)
157
continue;
158
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) {
165
Counter++;
166
if (!MDT.dominates(NextMI, I->getParent()))
167
Dominates = false;
168
}
169
170
if ((!Dominates) || (Counter < 3))
171
continue;
172
173
// If we reach here, we have met all the conditions required for the
174
// replacement of the absolute instruction.
175
LLVM_DEBUG({
176
dbgs() << "Found a pair of instructions for absolute-set "
177
<< (IsLoad ? "load" : "store") << "\n";
178
dbgs() << *MI;
179
dbgs() << *NextMI;
180
});
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);
192
}
193
194
MachineOperand ImmOperand = MI->getOperand(1);
195
if (IsGlobal)
196
MIB.addGlobalAddress(ImmOperand.getGlobal(), ImmOperand.getOffset(),
197
ImmOperand.getTargetFlags());
198
else
199
MIB.addImm(ImmOperand.getImm());
200
201
if (IsLoad)
202
MIB->getOperand(0).setSubReg(MO0.getSubReg());
203
else
204
MIB.addReg(LoadStoreReg, 0, MO0.getSubReg());
205
206
LLVM_DEBUG(dbgs() << "Replaced with " << *MIB << "\n");
207
// Erase the instructions that got replaced.
208
MII = MBB->erase(MI);
209
--MII;
210
NextMI->getParent()->erase(NextMI);
211
}
212
}
213
214
return true;
215
}
216
217
bool HexagonGenMemAbsolute::isValidIndexedLoad(int &Opc, int &NewOpc) {
218
219
bool Result = true;
220
switch (Opc) {
221
case Hexagon::L2_loadrb_io:
222
NewOpc = Hexagon::L4_loadrb_ap;
223
break;
224
case Hexagon::L2_loadrh_io:
225
NewOpc = Hexagon::L4_loadrh_ap;
226
break;
227
case Hexagon::L2_loadri_io:
228
NewOpc = Hexagon::L4_loadri_ap;
229
break;
230
case Hexagon::L2_loadrd_io:
231
NewOpc = Hexagon::L4_loadrd_ap;
232
break;
233
case Hexagon::L2_loadruh_io:
234
NewOpc = Hexagon::L4_loadruh_ap;
235
break;
236
case Hexagon::L2_loadrub_io:
237
NewOpc = Hexagon::L4_loadrub_ap;
238
break;
239
default:
240
Result = false;
241
}
242
243
return Result;
244
}
245
246
bool HexagonGenMemAbsolute::isValidIndexedStore(int &Opc, int &NewOpc) {
247
248
bool Result = true;
249
switch (Opc) {
250
case Hexagon::S2_storerd_io:
251
NewOpc = Hexagon::S4_storerd_ap;
252
break;
253
case Hexagon::S2_storeri_io:
254
NewOpc = Hexagon::S4_storeri_ap;
255
break;
256
case Hexagon::S2_storerh_io:
257
NewOpc = Hexagon::S4_storerh_ap;
258
break;
259
case Hexagon::S2_storerb_io:
260
NewOpc = Hexagon::S4_storerb_ap;
261
break;
262
default:
263
Result = false;
264
}
265
266
return Result;
267
}
268
269
//===----------------------------------------------------------------------===//
270
// Public Constructor Functions
271
//===----------------------------------------------------------------------===//
272
273
FunctionPass *llvm::createHexagonGenMemAbsolute() {
274
return new HexagonGenMemAbsolute();
275
}
276
277