1 | //===-- VERegisterInfo.cpp - VE Register Information ----------------------===// |
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 file contains the VE implementation of the TargetRegisterInfo class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "VERegisterInfo.h" |
14 | #include "VE.h" |
15 | #include "VESubtarget.h" |
16 | #include "llvm/ADT/BitVector.h" |
17 | #include "llvm/ADT/STLExtras.h" |
18 | #include "llvm/CodeGen/MachineFrameInfo.h" |
19 | #include "llvm/CodeGen/MachineFunction.h" |
20 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
21 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
22 | #include "llvm/CodeGen/TargetInstrInfo.h" |
23 | #include "llvm/IR/Type.h" |
24 | #include "llvm/Support/CommandLine.h" |
25 | #include "llvm/Support/Debug.h" |
26 | #include "llvm/Support/ErrorHandling.h" |
27 | |
28 | using namespace llvm; |
29 | |
30 | #define DEBUG_TYPE "ve-register-info" |
31 | |
32 | #define GET_REGINFO_TARGET_DESC |
33 | #include "VEGenRegisterInfo.inc" |
34 | |
35 | // VE uses %s10 == %lp to keep return address |
36 | VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {} |
37 | |
38 | const MCPhysReg * |
39 | VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { |
40 | switch (MF->getFunction().getCallingConv()) { |
41 | case CallingConv::Fast: |
42 | // Being explicit (same as standard CC). |
43 | default: |
44 | return CSR_SaveList; |
45 | case CallingConv::PreserveAll: |
46 | return CSR_preserve_all_SaveList; |
47 | } |
48 | } |
49 | |
50 | const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF, |
51 | CallingConv::ID CC) const { |
52 | switch (CC) { |
53 | case CallingConv::Fast: |
54 | // Being explicit (same as standard CC). |
55 | default: |
56 | return CSR_RegMask; |
57 | case CallingConv::PreserveAll: |
58 | return CSR_preserve_all_RegMask; |
59 | } |
60 | } |
61 | |
62 | const uint32_t *VERegisterInfo::getNoPreservedMask() const { |
63 | return CSR_NoRegs_RegMask; |
64 | } |
65 | |
66 | BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const { |
67 | BitVector Reserved(getNumRegs()); |
68 | |
69 | const Register ReservedRegs[] = { |
70 | VE::SX8, // Stack limit |
71 | VE::SX9, // Frame pointer |
72 | VE::SX10, // Link register (return address) |
73 | VE::SX11, // Stack pointer |
74 | |
75 | // FIXME: maybe not need to be reserved |
76 | VE::SX12, // Outer register |
77 | VE::SX13, // Id register for dynamic linker |
78 | |
79 | VE::SX14, // Thread pointer |
80 | VE::SX15, // Global offset table register |
81 | VE::SX16, // Procedure linkage table register |
82 | VE::SX17, // Linkage-area register |
83 | // sx18-sx33 are callee-saved registers |
84 | // sx34-sx63 are temporary registers |
85 | }; |
86 | |
87 | for (auto R : ReservedRegs) |
88 | for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid(); |
89 | ++ItAlias) |
90 | Reserved.set(*ItAlias); |
91 | |
92 | // Reserve constant registers. |
93 | Reserved.set(VE::VM0); |
94 | Reserved.set(VE::VMP0); |
95 | |
96 | return Reserved; |
97 | } |
98 | |
99 | const TargetRegisterClass * |
100 | VERegisterInfo::getPointerRegClass(const MachineFunction &MF, |
101 | unsigned Kind) const { |
102 | return &VE::I64RegClass; |
103 | } |
104 | |
105 | static unsigned offsetToDisp(MachineInstr &MI) { |
106 | // Default offset in instruction's operands (reg+reg+imm). |
107 | unsigned OffDisp = 2; |
108 | |
109 | #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii |
110 | |
111 | { |
112 | using namespace llvm::VE; |
113 | switch (MI.getOpcode()) { |
114 | case INLINEASM: |
115 | case RRCAS_multi_cases(TS1AML): |
116 | case RRCAS_multi_cases(TS1AMW): |
117 | case RRCAS_multi_cases(CASL): |
118 | case RRCAS_multi_cases(CASW): |
119 | // These instructions use AS format (reg+imm). |
120 | OffDisp = 1; |
121 | break; |
122 | } |
123 | } |
124 | #undef RRCAS_multi_cases |
125 | |
126 | return OffDisp; |
127 | } |
128 | |
129 | namespace { |
130 | class EliminateFrameIndex { |
131 | const TargetInstrInfo &TII; |
132 | const TargetRegisterInfo &TRI; |
133 | const DebugLoc &DL; |
134 | MachineBasicBlock &MBB; |
135 | MachineBasicBlock::iterator II; |
136 | Register clobber; |
137 | |
138 | // Some helper functions for the ease of instruction building. |
139 | MachineFunction &getFunc() const { return *MBB.getParent(); } |
140 | inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const { |
141 | return TRI.getSubReg(Reg, Idx); |
142 | } |
143 | inline const MCInstrDesc &get(unsigned Opcode) const { |
144 | return TII.get(Opcode); |
145 | } |
146 | inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) { |
147 | return BuildMI(BB&: MBB, I: II, MIMD: DL, MCID, DestReg); |
148 | } |
149 | inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) { |
150 | return build(MCID: get(Opcode: InstOpc), DestReg); |
151 | } |
152 | inline MachineInstrBuilder build(const MCInstrDesc &MCID) { |
153 | return BuildMI(BB&: MBB, I: II, MIMD: DL, MCID); |
154 | } |
155 | inline MachineInstrBuilder build(unsigned InstOpc) { |
156 | return build(MCID: get(Opcode: InstOpc)); |
157 | } |
158 | |
159 | // Calculate an address of frame index from a frame register and a given |
160 | // offset if the offset doesn't fit in the immediate field. Use a clobber |
161 | // register to hold calculated address. |
162 | void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset, |
163 | int64_t Bytes = 0); |
164 | // Replace the frame index in \p MI with a frame register and a given offset |
165 | // if it fits in the immediate field. Otherwise, use pre-calculated address |
166 | // in a clobber regsiter. |
167 | void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset, |
168 | int FIOperandNum); |
169 | |
170 | // Expand and eliminate Frame Index of pseudo STQrii and LDQrii. |
171 | void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset, |
172 | int FIOperandNum); |
173 | void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset, |
174 | int FIOperandNum); |
175 | // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii. |
176 | void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset, |
177 | int FIOperandNum); |
178 | void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset, |
179 | int FIOperandNum); |
180 | // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii. |
181 | void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset, |
182 | int FIOperandNum); |
183 | void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset, |
184 | int FIOperandNum); |
185 | |
186 | public: |
187 | EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, |
188 | const DebugLoc &DL, MachineBasicBlock &MBB, |
189 | MachineBasicBlock::iterator II) |
190 | : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {} |
191 | |
192 | // Expand and eliminate Frame Index from MI |
193 | void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset, |
194 | int FIOperandNum); |
195 | }; |
196 | } // namespace |
197 | |
198 | // Prepare the frame index if it doesn't fit in the immediate field. Use |
199 | // clobber register to hold calculated address. |
200 | void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg, |
201 | int64_t &Offset, int64_t Bytes) { |
202 | if (isInt<32>(x: Offset) && isInt<32>(x: Offset + Bytes)) { |
203 | // If the offset is small enough to fit in the immediate field, directly |
204 | // encode it. So, nothing to prepare here. |
205 | return; |
206 | } |
207 | |
208 | // If the offset doesn't fit, emit following codes. This clobbers SX13 |
209 | // which we always know is available here. |
210 | // lea %clobber, Offset@lo |
211 | // and %clobber, %clobber, (32)0 |
212 | // lea.sl %clobber, Offset@hi(FrameReg, %clobber) |
213 | build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset)); |
214 | build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32)); |
215 | build(VE::LEASLrri, clobber) |
216 | .addReg(clobber) |
217 | .addReg(FrameReg) |
218 | .addImm(Hi_32(Offset)); |
219 | |
220 | // Use clobber register as a frame register and 0 offset |
221 | FrameReg = clobber; |
222 | Offset = 0; |
223 | } |
224 | |
225 | // Replace the frame index in \p MI with a proper byte and framereg offset. |
226 | void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg, |
227 | int64_t Offset, int FIOperandNum) { |
228 | assert(isInt<32>(Offset)); |
229 | |
230 | // The offset must be small enough to fit in the immediate field after |
231 | // call of prepareReplaceFI. Therefore, we directly encode it. |
232 | MI.getOperand(i: FIOperandNum).ChangeToRegister(Reg: FrameReg, isDef: false); |
233 | MI.getOperand(i: FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(ImmVal: Offset); |
234 | } |
235 | |
236 | void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg, |
237 | int64_t Offset, int FIOperandNum) { |
238 | assert(MI.getOpcode() == VE::STQrii); |
239 | LLVM_DEBUG(dbgs() << "processSTQ: " ; MI.dump()); |
240 | |
241 | prepareReplaceFI(MI, FrameReg, Offset, Bytes: 8); |
242 | |
243 | Register SrcReg = MI.getOperand(i: 3).getReg(); |
244 | Register SrcHiReg = getSubReg(SrcReg, VE::sub_even); |
245 | Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd); |
246 | // VE stores HiReg to 8(addr) and LoReg to 0(addr) |
247 | MachineInstr *StMI = |
248 | build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg); |
249 | replaceFI(MI&: *StMI, FrameReg, Offset, FIOperandNum: 0); |
250 | // Mutate to 'hi' store. |
251 | MI.setDesc(get(VE::STrii)); |
252 | MI.getOperand(i: 3).setReg(SrcHiReg); |
253 | Offset += 8; |
254 | replaceFI(MI, FrameReg, Offset, FIOperandNum); |
255 | } |
256 | |
257 | void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg, |
258 | int64_t Offset, int FIOperandNum) { |
259 | assert(MI.getOpcode() == VE::LDQrii); |
260 | LLVM_DEBUG(dbgs() << "processLDQ: " ; MI.dump()); |
261 | |
262 | prepareReplaceFI(MI, FrameReg, Offset, Bytes: 8); |
263 | |
264 | Register DestReg = MI.getOperand(i: 0).getReg(); |
265 | Register DestHiReg = getSubReg(DestReg, VE::sub_even); |
266 | Register DestLoReg = getSubReg(DestReg, VE::sub_odd); |
267 | // VE loads HiReg from 8(addr) and LoReg from 0(addr) |
268 | MachineInstr *StMI = |
269 | build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0); |
270 | replaceFI(MI&: *StMI, FrameReg, Offset, FIOperandNum: 1); |
271 | MI.setDesc(get(VE::LDrii)); |
272 | MI.getOperand(i: 0).setReg(DestHiReg); |
273 | Offset += 8; |
274 | replaceFI(MI, FrameReg, Offset, FIOperandNum); |
275 | } |
276 | |
277 | void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg, |
278 | int64_t Offset, int FIOperandNum) { |
279 | assert(MI.getOpcode() == VE::STVMrii); |
280 | LLVM_DEBUG(dbgs() << "processSTVM: " ; MI.dump()); |
281 | |
282 | // Original MI is: |
283 | // STVMrii frame-index, 0, offset, reg (, memory operand) |
284 | // Convert it to: |
285 | // SVMi tmp-reg, reg, 0 |
286 | // STrii frame-reg, 0, offset, tmp-reg |
287 | // SVMi tmp-reg, reg, 1 |
288 | // STrii frame-reg, 0, offset+8, tmp-reg |
289 | // SVMi tmp-reg, reg, 2 |
290 | // STrii frame-reg, 0, offset+16, tmp-reg |
291 | // SVMi tmp-reg, reg, 3 |
292 | // STrii frame-reg, 0, offset+24, tmp-reg |
293 | |
294 | prepareReplaceFI(MI, FrameReg, Offset, Bytes: 24); |
295 | |
296 | Register SrcReg = MI.getOperand(i: 3).getReg(); |
297 | bool isKill = MI.getOperand(i: 3).isKill(); |
298 | // FIXME: it would be better to scavenge a register here instead of |
299 | // reserving SX16 all of the time. |
300 | Register TmpReg = VE::SX16; |
301 | for (int i = 0; i < 3; ++i) { |
302 | build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i); |
303 | MachineInstr *StMI = |
304 | build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( |
305 | TmpReg, getKillRegState(true)); |
306 | replaceFI(MI&: *StMI, FrameReg, Offset, FIOperandNum: 0); |
307 | Offset += 8; |
308 | } |
309 | build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3); |
310 | MI.setDesc(get(VE::STrii)); |
311 | MI.getOperand(i: 3).ChangeToRegister(Reg: TmpReg, isDef: false, isImp: false, isKill: true); |
312 | replaceFI(MI, FrameReg, Offset, FIOperandNum); |
313 | } |
314 | |
315 | void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg, |
316 | int64_t Offset, int FIOperandNum) { |
317 | assert(MI.getOpcode() == VE::LDVMrii); |
318 | LLVM_DEBUG(dbgs() << "processLDVM: " ; MI.dump()); |
319 | |
320 | // Original MI is: |
321 | // LDVMri reg, frame-index, 0, offset (, memory operand) |
322 | // Convert it to: |
323 | // LDrii tmp-reg, frame-reg, 0, offset |
324 | // LVMir vm, 0, tmp-reg |
325 | // LDrii tmp-reg, frame-reg, 0, offset+8 |
326 | // LVMir_m vm, 1, tmp-reg, vm |
327 | // LDrii tmp-reg, frame-reg, 0, offset+16 |
328 | // LVMir_m vm, 2, tmp-reg, vm |
329 | // LDrii tmp-reg, frame-reg, 0, offset+24 |
330 | // LVMir_m vm, 3, tmp-reg, vm |
331 | |
332 | prepareReplaceFI(MI, FrameReg, Offset, Bytes: 24); |
333 | |
334 | Register DestReg = MI.getOperand(i: 0).getReg(); |
335 | // FIXME: it would be better to scavenge a register here instead of |
336 | // reserving SX16 all of the time. |
337 | unsigned TmpReg = VE::SX16; |
338 | for (int i = 0; i < 4; ++i) { |
339 | if (i != 3) { |
340 | MachineInstr *StMI = |
341 | build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); |
342 | replaceFI(MI&: *StMI, FrameReg, Offset, FIOperandNum: 1); |
343 | Offset += 8; |
344 | } else { |
345 | // Last LDrii replace the target instruction. |
346 | MI.setDesc(get(VE::LDrii)); |
347 | MI.getOperand(i: 0).ChangeToRegister(Reg: TmpReg, isDef: true); |
348 | } |
349 | // First LVM is LVMir. Others are LVMir_m. Last LVM places at the |
350 | // next of the target instruction. |
351 | if (i == 0) |
352 | build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true)); |
353 | else if (i != 3) |
354 | build(VE::LVMir_m, DestReg) |
355 | .addImm(i) |
356 | .addReg(TmpReg, getKillRegState(true)) |
357 | .addReg(DestReg); |
358 | else |
359 | BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg) |
360 | .addImm(3) |
361 | .addReg(TmpReg, getKillRegState(true)) |
362 | .addReg(DestReg); |
363 | } |
364 | replaceFI(MI, FrameReg, Offset, FIOperandNum); |
365 | } |
366 | |
367 | void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg, |
368 | int64_t Offset, int FIOperandNum) { |
369 | assert(MI.getOpcode() == VE::STVM512rii); |
370 | LLVM_DEBUG(dbgs() << "processSTVM512: " ; MI.dump()); |
371 | |
372 | prepareReplaceFI(MI, FrameReg, Offset, Bytes: 56); |
373 | |
374 | Register SrcReg = MI.getOperand(i: 3).getReg(); |
375 | Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd); |
376 | Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even); |
377 | bool isKill = MI.getOperand(i: 3).isKill(); |
378 | // FIXME: it would be better to scavenge a register here instead of |
379 | // reserving SX16 all of the time. |
380 | Register TmpReg = VE::SX16; |
381 | // store low part of VMP |
382 | MachineInstr *LastMI = nullptr; |
383 | for (int i = 0; i < 4; ++i) { |
384 | LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i); |
385 | MachineInstr *StMI = |
386 | build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( |
387 | TmpReg, getKillRegState(true)); |
388 | replaceFI(MI&: *StMI, FrameReg, Offset, FIOperandNum: 0); |
389 | Offset += 8; |
390 | } |
391 | if (isKill) |
392 | LastMI->addRegisterKilled(IncomingReg: SrcLoReg, RegInfo: &TRI, AddIfNotFound: true); |
393 | // store high part of VMP |
394 | for (int i = 0; i < 3; ++i) { |
395 | build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i); |
396 | MachineInstr *StMI = |
397 | build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( |
398 | TmpReg, getKillRegState(true)); |
399 | replaceFI(MI&: *StMI, FrameReg, Offset, FIOperandNum: 0); |
400 | Offset += 8; |
401 | } |
402 | LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3); |
403 | if (isKill) { |
404 | LastMI->addRegisterKilled(IncomingReg: SrcHiReg, RegInfo: &TRI, AddIfNotFound: true); |
405 | // Add implicit super-register kills to the particular MI. |
406 | LastMI->addRegisterKilled(IncomingReg: SrcReg, RegInfo: &TRI, AddIfNotFound: true); |
407 | } |
408 | MI.setDesc(get(VE::STrii)); |
409 | MI.getOperand(i: 3).ChangeToRegister(Reg: TmpReg, isDef: false, isImp: false, isKill: true); |
410 | replaceFI(MI, FrameReg, Offset, FIOperandNum); |
411 | } |
412 | |
413 | void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg, |
414 | int64_t Offset, int FIOperandNum) { |
415 | assert(MI.getOpcode() == VE::LDVM512rii); |
416 | LLVM_DEBUG(dbgs() << "processLDVM512: " ; MI.dump()); |
417 | |
418 | prepareReplaceFI(MI, FrameReg, Offset, Bytes: 56); |
419 | |
420 | Register DestReg = MI.getOperand(i: 0).getReg(); |
421 | Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd); |
422 | Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even); |
423 | // FIXME: it would be better to scavenge a register here instead of |
424 | // reserving SX16 all of the time. |
425 | Register TmpReg = VE::SX16; |
426 | build(VE::IMPLICIT_DEF, DestReg); |
427 | for (int i = 0; i < 4; ++i) { |
428 | MachineInstr *LdMI = |
429 | build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); |
430 | replaceFI(MI&: *LdMI, FrameReg, Offset, FIOperandNum: 1); |
431 | build(VE::LVMir_m, DestLoReg) |
432 | .addImm(i) |
433 | .addReg(TmpReg, getKillRegState(true)) |
434 | .addReg(DestLoReg); |
435 | Offset += 8; |
436 | } |
437 | for (int i = 0; i < 3; ++i) { |
438 | MachineInstr *LdMI = |
439 | build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); |
440 | replaceFI(MI&: *LdMI, FrameReg, Offset, FIOperandNum: 1); |
441 | build(VE::LVMir_m, DestHiReg) |
442 | .addImm(i) |
443 | .addReg(TmpReg, getKillRegState(true)) |
444 | .addReg(DestHiReg); |
445 | Offset += 8; |
446 | } |
447 | MI.setDesc(get(VE::LDrii)); |
448 | MI.getOperand(i: 0).ChangeToRegister(Reg: TmpReg, isDef: true); |
449 | BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg) |
450 | .addImm(3) |
451 | .addReg(TmpReg, getKillRegState(true)) |
452 | .addReg(DestHiReg); |
453 | replaceFI(MI, FrameReg, Offset, FIOperandNum); |
454 | } |
455 | |
456 | void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg, |
457 | int64_t Offset, int FIOperandNum) { |
458 | switch (MI.getOpcode()) { |
459 | case VE::STQrii: |
460 | processSTQ(MI, FrameReg, Offset, FIOperandNum); |
461 | return; |
462 | case VE::LDQrii: |
463 | processLDQ(MI, FrameReg, Offset, FIOperandNum); |
464 | return; |
465 | case VE::STVMrii: |
466 | processSTVM(MI, FrameReg, Offset, FIOperandNum); |
467 | return; |
468 | case VE::LDVMrii: |
469 | processLDVM(MI, FrameReg, Offset, FIOperandNum); |
470 | return; |
471 | case VE::STVM512rii: |
472 | processSTVM512(MI, FrameReg, Offset, FIOperandNum); |
473 | return; |
474 | case VE::LDVM512rii: |
475 | processLDVM512(MI, FrameReg, Offset, FIOperandNum); |
476 | return; |
477 | } |
478 | prepareReplaceFI(MI, FrameReg, Offset); |
479 | replaceFI(MI, FrameReg, Offset, FIOperandNum); |
480 | } |
481 | |
482 | bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, |
483 | int SPAdj, unsigned FIOperandNum, |
484 | RegScavenger *RS) const { |
485 | assert(SPAdj == 0 && "Unexpected" ); |
486 | |
487 | MachineInstr &MI = *II; |
488 | int FrameIndex = MI.getOperand(i: FIOperandNum).getIndex(); |
489 | |
490 | MachineFunction &MF = *MI.getParent()->getParent(); |
491 | const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>(); |
492 | const VEFrameLowering &TFI = *getFrameLowering(MF); |
493 | const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); |
494 | const VERegisterInfo &TRI = *Subtarget.getRegisterInfo(); |
495 | DebugLoc DL = MI.getDebugLoc(); |
496 | EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II); |
497 | |
498 | // Retrieve FrameReg and byte offset for stack slot. |
499 | Register FrameReg; |
500 | int64_t Offset = |
501 | TFI.getFrameIndexReference(MF, FI: FrameIndex, FrameReg).getFixed(); |
502 | Offset += MI.getOperand(i: FIOperandNum + offsetToDisp(MI)).getImm(); |
503 | |
504 | EFI.processMI(MI, FrameReg, Offset, FIOperandNum); |
505 | return false; |
506 | } |
507 | |
508 | Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const { |
509 | return VE::SX9; |
510 | } |
511 | |