[NFC][RISCV] Remove CFIIndex argument from allocateStack (#117871)
[llvm-project.git] / llvm / lib / Target / Hexagon / HexagonGenMemAbsolute.cpp
blob9aea7a9e076233e6e7d827e9e5f9441ca14e96fe
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 //===----------------------------------------------------------------------===//
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"
27 using namespace llvm;
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");
34 namespace llvm {
35 FunctionPass *createHexagonGenMemAbsolute();
36 void initializeHexagonGenMemAbsolutePass(PassRegistry &Registry);
37 } // namespace llvm
39 namespace {
41 class HexagonGenMemAbsolute : public MachineFunctionPass {
42 const HexagonInstrInfo *TII;
43 MachineRegisterInfo *MRI;
44 const TargetRegisterInfo *TRI;
46 public:
47 static char ID;
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;
64 private:
65 static bool isValidIndexedLoad(int &Opcode, int &NewOpcode);
66 static bool isValidIndexedStore(int &Opcode, int &NewOpcode);
68 } // namespace
70 char HexagonGenMemAbsolute::ID = 0;
72 INITIALIZE_PASS(HexagonGenMemAbsolute, "hexagon-gen-load-absolute",
73 "Hexagon Generate Load/Store Set Absolute Address Instruction",
74 false, false)
76 bool HexagonGenMemAbsolute::runOnMachineFunction(MachineFunction &Fn) {
77 if (skipFunction(Fn.getFunction()))
78 return false;
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();
91 ++MII) {
92 MachineInstr *MI = &*MII;
93 int Opc = MI->getOpcode();
94 if (Opc != Hexagon::CONST32 && Opc != Hexagon::A2_tfrsi)
95 continue;
97 const MachineOperand &MO = MI->getOperand(0);
98 if (!MO.isReg() || !MO.isDef())
99 continue;
101 unsigned DstReg = MO.getReg();
102 if (MRI->use_nodbg_empty(DstReg))
103 continue;
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();
110 int NewOpc;
111 bool IsLoad = isValidIndexedLoad(NextOpc, NewOpc);
113 if (!IsLoad && !isValidIndexedStore(NextOpc, NewOpc))
114 continue;
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))
121 continue;
122 RegPos = IsLoad ? 0 : 2;
124 bool IsGlobal = MI->getOperand(1).isGlobal();
125 if (!MI->getOperand(1).isImm() && !IsGlobal)
126 continue;
128 const MachineOperand *BaseOp = nullptr;
129 int64_t Offset;
130 bool Scalable;
131 TII->getMemOperandWithOffset(*NextMI, BaseOp, Offset, Scalable, TRI);
133 // Ensure BaseOp is non-null and register type.
134 if (!BaseOp || !BaseOp->isReg())
135 continue;
137 if (Scalable)
138 continue;
140 unsigned BaseReg = BaseOp->getReg();
141 if ((DstReg != BaseReg) || (Offset != 0))
142 continue;
144 const MachineOperand &MO0 = NextMI->getOperand(RegPos);
146 if (!MO0.isReg())
147 continue;
149 unsigned LoadStoreReg = MO0.getReg();
151 // Store: Bail out if the src and base are same (def and use on same
152 // register).
153 if (LoadStoreReg == BaseReg)
154 continue;
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) {
162 Counter++;
163 if (!MDT.dominates(NextMI, I->getParent()))
164 Dominates = false;
167 if ((!Dominates) || (Counter < 3))
168 continue;
170 // If we reach here, we have met all the conditions required for the
171 // replacement of the absolute instruction.
172 LLVM_DEBUG({
173 dbgs() << "Found a pair of instructions for absolute-set "
174 << (IsLoad ? "load" : "store") << "\n";
175 dbgs() << *MI;
176 dbgs() << *NextMI;
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);
192 if (IsGlobal)
193 MIB.addGlobalAddress(ImmOperand.getGlobal(), ImmOperand.getOffset(),
194 ImmOperand.getTargetFlags());
195 else
196 MIB.addImm(ImmOperand.getImm());
198 if (IsLoad)
199 MIB->getOperand(0).setSubReg(MO0.getSubReg());
200 else
201 MIB.addReg(LoadStoreReg, 0, MO0.getSubReg());
203 LLVM_DEBUG(dbgs() << "Replaced with " << *MIB << "\n");
204 // Erase the instructions that got replaced.
205 MII = MBB.erase(MI);
206 --MII;
207 NextMI->getParent()->erase(NextMI);
211 return true;
214 bool HexagonGenMemAbsolute::isValidIndexedLoad(int &Opc, int &NewOpc) {
216 bool Result = true;
217 switch (Opc) {
218 case Hexagon::L2_loadrb_io:
219 NewOpc = Hexagon::L4_loadrb_ap;
220 break;
221 case Hexagon::L2_loadrh_io:
222 NewOpc = Hexagon::L4_loadrh_ap;
223 break;
224 case Hexagon::L2_loadri_io:
225 NewOpc = Hexagon::L4_loadri_ap;
226 break;
227 case Hexagon::L2_loadrd_io:
228 NewOpc = Hexagon::L4_loadrd_ap;
229 break;
230 case Hexagon::L2_loadruh_io:
231 NewOpc = Hexagon::L4_loadruh_ap;
232 break;
233 case Hexagon::L2_loadrub_io:
234 NewOpc = Hexagon::L4_loadrub_ap;
235 break;
236 default:
237 Result = false;
240 return Result;
243 bool HexagonGenMemAbsolute::isValidIndexedStore(int &Opc, int &NewOpc) {
245 bool Result = true;
246 switch (Opc) {
247 case Hexagon::S2_storerd_io:
248 NewOpc = Hexagon::S4_storerd_ap;
249 break;
250 case Hexagon::S2_storeri_io:
251 NewOpc = Hexagon::S4_storeri_ap;
252 break;
253 case Hexagon::S2_storerh_io:
254 NewOpc = Hexagon::S4_storerh_ap;
255 break;
256 case Hexagon::S2_storerb_io:
257 NewOpc = Hexagon::S4_storerb_ap;
258 break;
259 default:
260 Result = false;
263 return Result;
266 //===----------------------------------------------------------------------===//
267 // Public Constructor Functions
268 //===----------------------------------------------------------------------===//
270 FunctionPass *llvm::createHexagonGenMemAbsolute() {
271 return new HexagonGenMemAbsolute();