1 //===-- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // The Hexagon processor has no instructions that load or store predicate
10 // registers directly. So, when these registers must be spilled a general
11 // purpose register must be found and the value copied to/from it from/to
12 // the predicate register. This code currently does not use the register
13 // scavenger mechanism available in the allocator. There are two registers
14 // reserved to allow spilling/restoring predicate registers. One is used to
15 // hold the predicate value. The other is used when stack frame offsets are
16 // too large.
17 //
18 //===----------------------------------------------------------------------===//
19
20 #include "Hexagon.h"
21 #include "HexagonMachineFunctionInfo.h"
22 #include "HexagonSubtarget.h"
23 #include "llvm/ADT/Statistic.h"
24 #include "llvm/CodeGen/LatencyPriorityQueue.h"
25 #include "llvm/CodeGen/MachineDominators.h"
26 #include "llvm/CodeGen/MachineFunctionPass.h"
27 #include "llvm/CodeGen/MachineInstrBuilder.h"
28 #include "llvm/CodeGen/MachineLoopInfo.h"
29 #include "llvm/CodeGen/MachineRegisterInfo.h"
30 #include "llvm/CodeGen/Passes.h"
31 #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
32 #include "llvm/CodeGen/SchedulerRegistry.h"
33 #include "llvm/Support/Compiler.h"
34 #include "llvm/Support/Debug.h"
35 #include "llvm/Support/MathExtras.h"
36 #include "llvm/Target/TargetInstrInfo.h"
37 #include "llvm/Target/TargetMachine.h"
38 #include "llvm/Target/TargetRegisterInfo.h"
39
40 using namespace llvm;
41
42
43 namespace llvm {
44 FunctionPass *createHexagonExpandPredSpillCode();
45 void initializeHexagonExpandPredSpillCodePass(PassRegistry&);
46 }
47
48
49 namespace {
50
51 class HexagonExpandPredSpillCode : public MachineFunctionPass {
52 public:
53 static char ID;
HexagonExpandPredSpillCode()54 HexagonExpandPredSpillCode() : MachineFunctionPass(ID) {
55 PassRegistry &Registry = *PassRegistry::getPassRegistry();
56 initializeHexagonExpandPredSpillCodePass(Registry);
57 }
58
getPassName() const59 const char *getPassName() const override {
60 return "Hexagon Expand Predicate Spill Code";
61 }
62 bool runOnMachineFunction(MachineFunction &Fn) override;
63 };
64
65
66 char HexagonExpandPredSpillCode::ID = 0;
67
68
runOnMachineFunction(MachineFunction & Fn)69 bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
70
71 const HexagonSubtarget &QST = Fn.getSubtarget<HexagonSubtarget>();
72 const HexagonInstrInfo *TII = QST.getInstrInfo();
73
74 // Loop over all of the basic blocks.
75 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
76 MBBb != MBBe; ++MBBb) {
77 MachineBasicBlock *MBB = &*MBBb;
78 // Traverse the basic block.
79 for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
80 ++MII) {
81 MachineInstr *MI = MII;
82 int Opc = MI->getOpcode();
83 if (Opc == Hexagon::S2_storerb_pci_pseudo ||
84 Opc == Hexagon::S2_storerh_pci_pseudo ||
85 Opc == Hexagon::S2_storeri_pci_pseudo ||
86 Opc == Hexagon::S2_storerd_pci_pseudo ||
87 Opc == Hexagon::S2_storerf_pci_pseudo) {
88 unsigned Opcode;
89 if (Opc == Hexagon::S2_storerd_pci_pseudo)
90 Opcode = Hexagon::S2_storerd_pci;
91 else if (Opc == Hexagon::S2_storeri_pci_pseudo)
92 Opcode = Hexagon::S2_storeri_pci;
93 else if (Opc == Hexagon::S2_storerh_pci_pseudo)
94 Opcode = Hexagon::S2_storerh_pci;
95 else if (Opc == Hexagon::S2_storerf_pci_pseudo)
96 Opcode = Hexagon::S2_storerf_pci;
97 else if (Opc == Hexagon::S2_storerb_pci_pseudo)
98 Opcode = Hexagon::S2_storerb_pci;
99 else
100 llvm_unreachable("wrong Opc");
101 MachineOperand &Op0 = MI->getOperand(0);
102 MachineOperand &Op1 = MI->getOperand(1);
103 MachineOperand &Op2 = MI->getOperand(2);
104 MachineOperand &Op3 = MI->getOperand(3); // Modifier value.
105 MachineOperand &Op4 = MI->getOperand(4);
106 // Emit a "C6 = Rn, C6 is the control register for M0".
107 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
108 Hexagon::C6)->addOperand(Op3);
109 // Replace the pseude circ_ldd by the real circ_ldd.
110 MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
111 TII->get(Opcode));
112 NewMI->addOperand(Op0);
113 NewMI->addOperand(Op1);
114 NewMI->addOperand(Op4);
115 NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
116 false, /*isDef*/
117 false, /*isImpl*/
118 true /*isKill*/));
119 NewMI->addOperand(Op2);
120 MII = MBB->erase(MI);
121 --MII;
122 } else if (Opc == Hexagon::L2_loadrd_pci_pseudo ||
123 Opc == Hexagon::L2_loadri_pci_pseudo ||
124 Opc == Hexagon::L2_loadrh_pci_pseudo ||
125 Opc == Hexagon::L2_loadruh_pci_pseudo||
126 Opc == Hexagon::L2_loadrb_pci_pseudo ||
127 Opc == Hexagon::L2_loadrub_pci_pseudo) {
128 unsigned Opcode;
129 if (Opc == Hexagon::L2_loadrd_pci_pseudo)
130 Opcode = Hexagon::L2_loadrd_pci;
131 else if (Opc == Hexagon::L2_loadri_pci_pseudo)
132 Opcode = Hexagon::L2_loadri_pci;
133 else if (Opc == Hexagon::L2_loadrh_pci_pseudo)
134 Opcode = Hexagon::L2_loadrh_pci;
135 else if (Opc == Hexagon::L2_loadruh_pci_pseudo)
136 Opcode = Hexagon::L2_loadruh_pci;
137 else if (Opc == Hexagon::L2_loadrb_pci_pseudo)
138 Opcode = Hexagon::L2_loadrb_pci;
139 else if (Opc == Hexagon::L2_loadrub_pci_pseudo)
140 Opcode = Hexagon::L2_loadrub_pci;
141 else
142 llvm_unreachable("wrong Opc");
143
144 MachineOperand &Op0 = MI->getOperand(0);
145 MachineOperand &Op1 = MI->getOperand(1);
146 MachineOperand &Op2 = MI->getOperand(2);
147 MachineOperand &Op4 = MI->getOperand(4); // Modifier value.
148 MachineOperand &Op5 = MI->getOperand(5);
149 // Emit a "C6 = Rn, C6 is the control register for M0".
150 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
151 Hexagon::C6)->addOperand(Op4);
152 // Replace the pseude circ_ldd by the real circ_ldd.
153 MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
154 TII->get(Opcode));
155 NewMI->addOperand(Op1);
156 NewMI->addOperand(Op0);
157 NewMI->addOperand(Op2);
158 NewMI->addOperand(Op5);
159 NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
160 false, /*isDef*/
161 false, /*isImpl*/
162 true /*isKill*/));
163 MII = MBB->erase(MI);
164 --MII;
165 } else if (Opc == Hexagon::L2_loadrd_pbr_pseudo ||
166 Opc == Hexagon::L2_loadri_pbr_pseudo ||
167 Opc == Hexagon::L2_loadrh_pbr_pseudo ||
168 Opc == Hexagon::L2_loadruh_pbr_pseudo||
169 Opc == Hexagon::L2_loadrb_pbr_pseudo ||
170 Opc == Hexagon::L2_loadrub_pbr_pseudo) {
171 unsigned Opcode;
172 if (Opc == Hexagon::L2_loadrd_pbr_pseudo)
173 Opcode = Hexagon::L2_loadrd_pbr;
174 else if (Opc == Hexagon::L2_loadri_pbr_pseudo)
175 Opcode = Hexagon::L2_loadri_pbr;
176 else if (Opc == Hexagon::L2_loadrh_pbr_pseudo)
177 Opcode = Hexagon::L2_loadrh_pbr;
178 else if (Opc == Hexagon::L2_loadruh_pbr_pseudo)
179 Opcode = Hexagon::L2_loadruh_pbr;
180 else if (Opc == Hexagon::L2_loadrb_pbr_pseudo)
181 Opcode = Hexagon::L2_loadrb_pbr;
182 else if (Opc == Hexagon::L2_loadrub_pbr_pseudo)
183 Opcode = Hexagon::L2_loadrub_pbr;
184 else
185 llvm_unreachable("wrong Opc");
186 MachineOperand &Op0 = MI->getOperand(0);
187 MachineOperand &Op1 = MI->getOperand(1);
188 MachineOperand &Op2 = MI->getOperand(2);
189 MachineOperand &Op4 = MI->getOperand(4); // Modifier value.
190 // Emit a "C6 = Rn, C6 is the control register for M0".
191 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
192 Hexagon::C6)->addOperand(Op4);
193 // Replace the pseudo brev_ldd by the real brev_ldd.
194 MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
195 TII->get(Opcode));
196 NewMI->addOperand(Op1);
197 NewMI->addOperand(Op0);
198 NewMI->addOperand(Op2);
199 NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
200 false, /*isDef*/
201 false, /*isImpl*/
202 true /*isKill*/));
203 MII = MBB->erase(MI);
204 --MII;
205 } else if (Opc == Hexagon::S2_storerd_pbr_pseudo ||
206 Opc == Hexagon::S2_storeri_pbr_pseudo ||
207 Opc == Hexagon::S2_storerh_pbr_pseudo ||
208 Opc == Hexagon::S2_storerb_pbr_pseudo ||
209 Opc == Hexagon::S2_storerf_pbr_pseudo) {
210 unsigned Opcode;
211 if (Opc == Hexagon::S2_storerd_pbr_pseudo)
212 Opcode = Hexagon::S2_storerd_pbr;
213 else if (Opc == Hexagon::S2_storeri_pbr_pseudo)
214 Opcode = Hexagon::S2_storeri_pbr;
215 else if (Opc == Hexagon::S2_storerh_pbr_pseudo)
216 Opcode = Hexagon::S2_storerh_pbr;
217 else if (Opc == Hexagon::S2_storerf_pbr_pseudo)
218 Opcode = Hexagon::S2_storerf_pbr;
219 else if (Opc == Hexagon::S2_storerb_pbr_pseudo)
220 Opcode = Hexagon::S2_storerb_pbr;
221 else
222 llvm_unreachable("wrong Opc");
223 MachineOperand &Op0 = MI->getOperand(0);
224 MachineOperand &Op1 = MI->getOperand(1);
225 MachineOperand &Op2 = MI->getOperand(2);
226 MachineOperand &Op3 = MI->getOperand(3); // Modifier value.
227 // Emit a "C6 = Rn, C6 is the control register for M0".
228 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
229 Hexagon::C6)->addOperand(Op3);
230 // Replace the pseudo brev_ldd by the real brev_ldd.
231 MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
232 TII->get(Opcode));
233 NewMI->addOperand(Op0);
234 NewMI->addOperand(Op1);
235 NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
236 false, /*isDef*/
237 false, /*isImpl*/
238 true /*isKill*/));
239 NewMI->addOperand(Op2);
240 MII = MBB->erase(MI);
241 --MII;
242 } else if (Opc == Hexagon::STriw_pred) {
243 // STriw_pred [R30], ofst, SrcReg;
244 unsigned FP = MI->getOperand(0).getReg();
245 assert(FP == QST.getRegisterInfo()->getFrameRegister() &&
246 "Not a Frame Pointer, Nor a Spill Slot");
247 assert(MI->getOperand(1).isImm() && "Not an offset");
248 int Offset = MI->getOperand(1).getImm();
249 int SrcReg = MI->getOperand(2).getReg();
250 assert(Hexagon::PredRegsRegClass.contains(SrcReg) &&
251 "Not a predicate register");
252 if (!TII->isValidOffset(Hexagon::S2_storeri_io, Offset)) {
253 if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) {
254 BuildMI(*MBB, MII, MI->getDebugLoc(),
255 TII->get(Hexagon::CONST32_Int_Real),
256 HEXAGON_RESERVED_REG_1).addImm(Offset);
257 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add),
258 HEXAGON_RESERVED_REG_1)
259 .addReg(FP).addReg(HEXAGON_RESERVED_REG_1);
260 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
261 HEXAGON_RESERVED_REG_2).addReg(SrcReg);
262 BuildMI(*MBB, MII, MI->getDebugLoc(),
263 TII->get(Hexagon::S2_storeri_io))
264 .addReg(HEXAGON_RESERVED_REG_1)
265 .addImm(0).addReg(HEXAGON_RESERVED_REG_2);
266 } else {
267 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi),
268 HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
269 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
270 HEXAGON_RESERVED_REG_2).addReg(SrcReg);
271 BuildMI(*MBB, MII, MI->getDebugLoc(),
272 TII->get(Hexagon::S2_storeri_io))
273 .addReg(HEXAGON_RESERVED_REG_1)
274 .addImm(0)
275 .addReg(HEXAGON_RESERVED_REG_2);
276 }
277 } else {
278 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
279 HEXAGON_RESERVED_REG_2).addReg(SrcReg);
280 BuildMI(*MBB, MII, MI->getDebugLoc(),
281 TII->get(Hexagon::S2_storeri_io)).
282 addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2);
283 }
284 MII = MBB->erase(MI);
285 --MII;
286 } else if (Opc == Hexagon::LDriw_pred) {
287 // DstReg = LDriw_pred [R30], ofst.
288 int DstReg = MI->getOperand(0).getReg();
289 assert(Hexagon::PredRegsRegClass.contains(DstReg) &&
290 "Not a predicate register");
291 unsigned FP = MI->getOperand(1).getReg();
292 assert(FP == QST.getRegisterInfo()->getFrameRegister() &&
293 "Not a Frame Pointer, Nor a Spill Slot");
294 assert(MI->getOperand(2).isImm() && "Not an offset");
295 int Offset = MI->getOperand(2).getImm();
296 if (!TII->isValidOffset(Hexagon::L2_loadri_io, Offset)) {
297 if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) {
298 BuildMI(*MBB, MII, MI->getDebugLoc(),
299 TII->get(Hexagon::CONST32_Int_Real),
300 HEXAGON_RESERVED_REG_1).addImm(Offset);
301 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add),
302 HEXAGON_RESERVED_REG_1)
303 .addReg(FP)
304 .addReg(HEXAGON_RESERVED_REG_1);
305 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
306 HEXAGON_RESERVED_REG_2)
307 .addReg(HEXAGON_RESERVED_REG_1)
308 .addImm(0);
309 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
310 DstReg).addReg(HEXAGON_RESERVED_REG_2);
311 } else {
312 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi),
313 HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
314 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
315 HEXAGON_RESERVED_REG_2)
316 .addReg(HEXAGON_RESERVED_REG_1)
317 .addImm(0);
318 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
319 DstReg).addReg(HEXAGON_RESERVED_REG_2);
320 }
321 } else {
322 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
323 HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset);
324 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
325 DstReg).addReg(HEXAGON_RESERVED_REG_2);
326 }
327 MII = MBB->erase(MI);
328 --MII;
329 }
330 }
331 }
332
333 return true;
334 }
335
336 }
337
338 //===----------------------------------------------------------------------===//
339 // Public Constructor Functions
340 //===----------------------------------------------------------------------===//
341
initializePassOnce(PassRegistry & Registry)342 static void initializePassOnce(PassRegistry &Registry) {
343 const char *Name = "Hexagon Expand Predicate Spill Code";
344 PassInfo *PI = new PassInfo(Name, "hexagon-spill-pred",
345 &HexagonExpandPredSpillCode::ID,
346 nullptr, false, false);
347 Registry.registerPass(*PI, true);
348 }
349
initializeHexagonExpandPredSpillCodePass(PassRegistry & Registry)350 void llvm::initializeHexagonExpandPredSpillCodePass(PassRegistry &Registry) {
351 CALL_ONCE_INITIALIZATION(initializePassOnce)
352 }
353
354 FunctionPass*
createHexagonExpandPredSpillCode()355 llvm::createHexagonExpandPredSpillCode() {
356 return new HexagonExpandPredSpillCode();
357 }
358