xref: /freebsd/contrib/llvm-project/llvm/lib/Target/VE/VERegisterInfo.cpp (revision fcaf7f8644a9988098ac6be2165bce3ea4786e91)
1480093f4SDimitry Andric //===-- VERegisterInfo.cpp - VE Register Information ----------------------===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric //
9480093f4SDimitry Andric // This file contains the VE implementation of the TargetRegisterInfo class.
10480093f4SDimitry Andric //
11480093f4SDimitry Andric //===----------------------------------------------------------------------===//
12480093f4SDimitry Andric 
13480093f4SDimitry Andric #include "VERegisterInfo.h"
14480093f4SDimitry Andric #include "VE.h"
15480093f4SDimitry Andric #include "VESubtarget.h"
16480093f4SDimitry Andric #include "llvm/ADT/BitVector.h"
17480093f4SDimitry Andric #include "llvm/ADT/STLExtras.h"
18480093f4SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
19480093f4SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
20480093f4SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
21480093f4SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
22480093f4SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
23480093f4SDimitry Andric #include "llvm/IR/Type.h"
24480093f4SDimitry Andric #include "llvm/Support/CommandLine.h"
25e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h"
26480093f4SDimitry Andric #include "llvm/Support/ErrorHandling.h"
27480093f4SDimitry Andric 
28480093f4SDimitry Andric using namespace llvm;
29480093f4SDimitry Andric 
30753f127fSDimitry Andric #define DEBUG_TYPE "ve-register-info"
31753f127fSDimitry Andric 
32480093f4SDimitry Andric #define GET_REGINFO_TARGET_DESC
33480093f4SDimitry Andric #include "VEGenRegisterInfo.inc"
34480093f4SDimitry Andric 
35480093f4SDimitry Andric // VE uses %s10 == %lp to keep return address
36480093f4SDimitry Andric VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}
37480093f4SDimitry Andric 
38480093f4SDimitry Andric const MCPhysReg *
39480093f4SDimitry Andric VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
405ffd83dbSDimitry Andric   switch (MF->getFunction().getCallingConv()) {
41e8d8bef9SDimitry Andric   case CallingConv::Fast:
42e8d8bef9SDimitry Andric     // Being explicit (same as standard CC).
435ffd83dbSDimitry Andric   default:
44480093f4SDimitry Andric     return CSR_SaveList;
455ffd83dbSDimitry Andric   case CallingConv::PreserveAll:
465ffd83dbSDimitry Andric     return CSR_preserve_all_SaveList;
475ffd83dbSDimitry Andric   }
48480093f4SDimitry Andric }
49480093f4SDimitry Andric 
50480093f4SDimitry Andric const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF,
51480093f4SDimitry Andric                                                      CallingConv::ID CC) const {
525ffd83dbSDimitry Andric   switch (CC) {
53e8d8bef9SDimitry Andric   case CallingConv::Fast:
54e8d8bef9SDimitry Andric     // Being explicit (same as standard CC).
555ffd83dbSDimitry Andric   default:
56480093f4SDimitry Andric     return CSR_RegMask;
575ffd83dbSDimitry Andric   case CallingConv::PreserveAll:
585ffd83dbSDimitry Andric     return CSR_preserve_all_RegMask;
595ffd83dbSDimitry Andric   }
60480093f4SDimitry Andric }
61480093f4SDimitry Andric 
62480093f4SDimitry Andric const uint32_t *VERegisterInfo::getNoPreservedMask() const {
63480093f4SDimitry Andric   return CSR_NoRegs_RegMask;
64480093f4SDimitry Andric }
65480093f4SDimitry Andric 
66480093f4SDimitry Andric BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {
67480093f4SDimitry Andric   BitVector Reserved(getNumRegs());
68480093f4SDimitry Andric 
695ffd83dbSDimitry Andric   const Register ReservedRegs[] = {
705ffd83dbSDimitry Andric       VE::SX8,  // Stack limit
715ffd83dbSDimitry Andric       VE::SX9,  // Frame pointer
725ffd83dbSDimitry Andric       VE::SX10, // Link register (return address)
735ffd83dbSDimitry Andric       VE::SX11, // Stack pointer
74480093f4SDimitry Andric 
755ffd83dbSDimitry Andric       // FIXME: maybe not need to be reserved
765ffd83dbSDimitry Andric       VE::SX12, // Outer register
775ffd83dbSDimitry Andric       VE::SX13, // Id register for dynamic linker
78480093f4SDimitry Andric 
795ffd83dbSDimitry Andric       VE::SX14, // Thread pointer
805ffd83dbSDimitry Andric       VE::SX15, // Global offset table register
815ffd83dbSDimitry Andric       VE::SX16, // Procedure linkage table register
825ffd83dbSDimitry Andric       VE::SX17, // Linkage-area register
83480093f4SDimitry Andric                 // sx18-sx33 are callee-saved registers
84480093f4SDimitry Andric                 // sx34-sx63 are temporary registers
855ffd83dbSDimitry Andric   };
865ffd83dbSDimitry Andric 
875ffd83dbSDimitry Andric   for (auto R : ReservedRegs)
885ffd83dbSDimitry Andric     for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid();
895ffd83dbSDimitry Andric          ++ItAlias)
905ffd83dbSDimitry Andric       Reserved.set(*ItAlias);
91480093f4SDimitry Andric 
92e8d8bef9SDimitry Andric   // Reserve constant registers.
93e8d8bef9SDimitry Andric   Reserved.set(VE::VM0);
94e8d8bef9SDimitry Andric   Reserved.set(VE::VMP0);
95e8d8bef9SDimitry Andric 
96480093f4SDimitry Andric   return Reserved;
97480093f4SDimitry Andric }
98480093f4SDimitry Andric 
99e8d8bef9SDimitry Andric bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const {
100e8d8bef9SDimitry Andric   switch (PhysReg) {
101e8d8bef9SDimitry Andric   case VE::VM0:
102e8d8bef9SDimitry Andric   case VE::VMP0:
103e8d8bef9SDimitry Andric     return true;
104e8d8bef9SDimitry Andric   default:
105e8d8bef9SDimitry Andric     return false;
106e8d8bef9SDimitry Andric   }
107e8d8bef9SDimitry Andric }
108480093f4SDimitry Andric 
109480093f4SDimitry Andric const TargetRegisterClass *
110480093f4SDimitry Andric VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
111480093f4SDimitry Andric                                    unsigned Kind) const {
112480093f4SDimitry Andric   return &VE::I64RegClass;
113480093f4SDimitry Andric }
114480093f4SDimitry Andric 
115e8d8bef9SDimitry Andric static unsigned offsetToDisp(MachineInstr &MI) {
116e8d8bef9SDimitry Andric   // Default offset in instruction's operands (reg+reg+imm).
117e8d8bef9SDimitry Andric   unsigned OffDisp = 2;
118e8d8bef9SDimitry Andric 
119e8d8bef9SDimitry Andric #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
120e8d8bef9SDimitry Andric 
121e8d8bef9SDimitry Andric   {
122e8d8bef9SDimitry Andric     using namespace llvm::VE;
123e8d8bef9SDimitry Andric     switch (MI.getOpcode()) {
124e8d8bef9SDimitry Andric     case RRCAS_multi_cases(TS1AML):
125e8d8bef9SDimitry Andric     case RRCAS_multi_cases(TS1AMW):
126e8d8bef9SDimitry Andric     case RRCAS_multi_cases(CASL):
127e8d8bef9SDimitry Andric     case RRCAS_multi_cases(CASW):
128e8d8bef9SDimitry Andric       // These instructions use AS format (reg+imm).
129e8d8bef9SDimitry Andric       OffDisp = 1;
130e8d8bef9SDimitry Andric       break;
131e8d8bef9SDimitry Andric     }
132e8d8bef9SDimitry Andric   }
133e8d8bef9SDimitry Andric #undef RRCAS_multi_cases
134e8d8bef9SDimitry Andric 
135e8d8bef9SDimitry Andric   return OffDisp;
136e8d8bef9SDimitry Andric }
137e8d8bef9SDimitry Andric 
138753f127fSDimitry Andric class EliminateFrameIndex {
139753f127fSDimitry Andric   const TargetInstrInfo &TII;
140753f127fSDimitry Andric   const TargetRegisterInfo &TRI;
141753f127fSDimitry Andric   const DebugLoc &DL;
142753f127fSDimitry Andric   MachineBasicBlock &MBB;
143753f127fSDimitry Andric   MachineBasicBlock::iterator II;
144753f127fSDimitry Andric   Register clobber;
145753f127fSDimitry Andric 
146753f127fSDimitry Andric   // Some helper functions for the ease of instruction building.
147753f127fSDimitry Andric   MachineFunction &getFunc() const { return *MBB.getParent(); }
148753f127fSDimitry Andric   inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {
149753f127fSDimitry Andric     return TRI.getSubReg(Reg, Idx);
150753f127fSDimitry Andric   }
151753f127fSDimitry Andric   inline const MCInstrDesc &get(unsigned Opcode) const {
152753f127fSDimitry Andric     return TII.get(Opcode);
153753f127fSDimitry Andric   }
154753f127fSDimitry Andric   inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {
155753f127fSDimitry Andric     return BuildMI(MBB, II, DL, MCID, DestReg);
156753f127fSDimitry Andric   }
157753f127fSDimitry Andric   inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {
158753f127fSDimitry Andric     return build(get(InstOpc), DestReg);
159753f127fSDimitry Andric   }
160753f127fSDimitry Andric   inline MachineInstrBuilder build(const MCInstrDesc &MCID) {
161753f127fSDimitry Andric     return BuildMI(MBB, II, DL, MCID);
162753f127fSDimitry Andric   }
163753f127fSDimitry Andric   inline MachineInstrBuilder build(unsigned InstOpc) {
164753f127fSDimitry Andric     return build(get(InstOpc));
165753f127fSDimitry Andric   }
166753f127fSDimitry Andric 
167753f127fSDimitry Andric   // Calculate an address of frame index from a frame register and a given
168753f127fSDimitry Andric   // offset if the offset doesn't fit in the immediate field.  Use a clobber
169753f127fSDimitry Andric   // register to hold calculated address.
170753f127fSDimitry Andric   void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,
171753f127fSDimitry Andric                         int64_t Bytes = 0);
172753f127fSDimitry Andric   // Replace the frame index in \p MI with a frame register and a given offset
173753f127fSDimitry Andric   // if it fits in the immediate field.  Otherwise, use pre-calculated address
174753f127fSDimitry Andric   // in a clobber regsiter.
175753f127fSDimitry Andric   void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,
176753f127fSDimitry Andric                  int FIOperandNum);
177753f127fSDimitry Andric 
178753f127fSDimitry Andric   // Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
179753f127fSDimitry Andric   void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
180753f127fSDimitry Andric                   int FIOperandNum);
181753f127fSDimitry Andric   void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
182753f127fSDimitry Andric                   int FIOperandNum);
183*fcaf7f86SDimitry Andric   // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.
184*fcaf7f86SDimitry Andric   void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
185*fcaf7f86SDimitry Andric                    int FIOperandNum);
186*fcaf7f86SDimitry Andric   void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
187*fcaf7f86SDimitry Andric                    int FIOperandNum);
188*fcaf7f86SDimitry Andric   // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.
189*fcaf7f86SDimitry Andric   void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
190*fcaf7f86SDimitry Andric                       int FIOperandNum);
191*fcaf7f86SDimitry Andric   void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
192*fcaf7f86SDimitry Andric                       int FIOperandNum);
193753f127fSDimitry Andric 
194753f127fSDimitry Andric public:
195753f127fSDimitry Andric   EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
196753f127fSDimitry Andric                       const DebugLoc &DL, MachineBasicBlock &MBB,
197753f127fSDimitry Andric                       MachineBasicBlock::iterator II)
198753f127fSDimitry Andric       : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}
199753f127fSDimitry Andric 
200753f127fSDimitry Andric   // Expand and eliminate Frame Index from MI
201753f127fSDimitry Andric   void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,
202753f127fSDimitry Andric                  int FIOperandNum);
203753f127fSDimitry Andric };
204753f127fSDimitry Andric 
205753f127fSDimitry Andric // Prepare the frame index if it doesn't fit in the immediate field.  Use
206753f127fSDimitry Andric // clobber register to hold calculated address.
207753f127fSDimitry Andric void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,
208753f127fSDimitry Andric                                            int64_t &Offset, int64_t Bytes) {
209753f127fSDimitry Andric   if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {
210753f127fSDimitry Andric     // If the offset is small enough to fit in the immediate field, directly
211753f127fSDimitry Andric     // encode it.  So, nothing to prepare here.
212753f127fSDimitry Andric     return;
213753f127fSDimitry Andric   }
214753f127fSDimitry Andric 
215753f127fSDimitry Andric   // If the offset doesn't fit, emit following codes.  This clobbers SX13
216753f127fSDimitry Andric   // which we always know is available here.
217753f127fSDimitry Andric   //   lea     %clobber, Offset@lo
218753f127fSDimitry Andric   //   and     %clobber, %clobber, (32)0
219753f127fSDimitry Andric   //   lea.sl  %clobber, Offset@hi(FrameReg, %clobber)
220753f127fSDimitry Andric   build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));
221753f127fSDimitry Andric   build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));
222753f127fSDimitry Andric   build(VE::LEASLrri, clobber)
223753f127fSDimitry Andric       .addReg(clobber)
224753f127fSDimitry Andric       .addReg(FrameReg)
225753f127fSDimitry Andric       .addImm(Hi_32(Offset));
226753f127fSDimitry Andric 
227753f127fSDimitry Andric   // Use clobber register as a frame register and 0 offset
228753f127fSDimitry Andric   FrameReg = clobber;
229753f127fSDimitry Andric   Offset = 0;
230753f127fSDimitry Andric }
231753f127fSDimitry Andric 
232753f127fSDimitry Andric // Replace the frame index in \p MI with a proper byte and framereg offset.
233753f127fSDimitry Andric void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,
234753f127fSDimitry Andric                                     int64_t Offset, int FIOperandNum) {
235753f127fSDimitry Andric   assert(isInt<32>(Offset));
236753f127fSDimitry Andric 
237753f127fSDimitry Andric   // The offset must be small enough to fit in the immediate field after
238753f127fSDimitry Andric   // call of prepareReplaceFI.  Therefore, we directly encode it.
2395ffd83dbSDimitry Andric   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
240e8d8bef9SDimitry Andric   MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
241480093f4SDimitry Andric }
242480093f4SDimitry Andric 
243753f127fSDimitry Andric void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,
244753f127fSDimitry Andric                                      int64_t Offset, int FIOperandNum) {
245753f127fSDimitry Andric   assert(MI.getOpcode() == VE::STQrii);
246753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());
247753f127fSDimitry Andric 
248753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 8);
249753f127fSDimitry Andric 
250753f127fSDimitry Andric   Register SrcReg = MI.getOperand(3).getReg();
251753f127fSDimitry Andric   Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
252753f127fSDimitry Andric   Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
253753f127fSDimitry Andric   // VE stores HiReg to 8(addr) and LoReg to 0(addr)
254753f127fSDimitry Andric   MachineInstr *StMI =
255753f127fSDimitry Andric       build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);
256753f127fSDimitry Andric   replaceFI(*StMI, FrameReg, Offset, 0);
257753f127fSDimitry Andric   // Mutate to 'hi' store.
258753f127fSDimitry Andric   MI.setDesc(get(VE::STrii));
259753f127fSDimitry Andric   MI.getOperand(3).setReg(SrcHiReg);
260753f127fSDimitry Andric   Offset += 8;
261753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
262753f127fSDimitry Andric }
263753f127fSDimitry Andric 
264753f127fSDimitry Andric void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,
265753f127fSDimitry Andric                                      int64_t Offset, int FIOperandNum) {
266753f127fSDimitry Andric   assert(MI.getOpcode() == VE::LDQrii);
267753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());
268753f127fSDimitry Andric 
269753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 8);
270753f127fSDimitry Andric 
271753f127fSDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
272753f127fSDimitry Andric   Register DestHiReg = getSubReg(DestReg, VE::sub_even);
273753f127fSDimitry Andric   Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
274753f127fSDimitry Andric   // VE loads HiReg from 8(addr) and LoReg from 0(addr)
275753f127fSDimitry Andric   MachineInstr *StMI =
276753f127fSDimitry Andric       build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);
277753f127fSDimitry Andric   replaceFI(*StMI, FrameReg, Offset, 1);
278753f127fSDimitry Andric   MI.setDesc(get(VE::LDrii));
279753f127fSDimitry Andric   MI.getOperand(0).setReg(DestHiReg);
280753f127fSDimitry Andric   Offset += 8;
281753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
282753f127fSDimitry Andric }
283753f127fSDimitry Andric 
284*fcaf7f86SDimitry Andric void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg,
285*fcaf7f86SDimitry Andric                                       int64_t Offset, int FIOperandNum) {
286*fcaf7f86SDimitry Andric   assert(MI.getOpcode() == VE::STVMrii);
287*fcaf7f86SDimitry Andric   LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump());
288*fcaf7f86SDimitry Andric 
289*fcaf7f86SDimitry Andric   // Original MI is:
290*fcaf7f86SDimitry Andric   //   STVMrii frame-index, 0, offset, reg (, memory operand)
291*fcaf7f86SDimitry Andric   // Convert it to:
292*fcaf7f86SDimitry Andric   //   SVMi   tmp-reg, reg, 0
293*fcaf7f86SDimitry Andric   //   STrii  frame-reg, 0, offset, tmp-reg
294*fcaf7f86SDimitry Andric   //   SVMi   tmp-reg, reg, 1
295*fcaf7f86SDimitry Andric   //   STrii  frame-reg, 0, offset+8, tmp-reg
296*fcaf7f86SDimitry Andric   //   SVMi   tmp-reg, reg, 2
297*fcaf7f86SDimitry Andric   //   STrii  frame-reg, 0, offset+16, tmp-reg
298*fcaf7f86SDimitry Andric   //   SVMi   tmp-reg, reg, 3
299*fcaf7f86SDimitry Andric   //   STrii  frame-reg, 0, offset+24, tmp-reg
300*fcaf7f86SDimitry Andric 
301*fcaf7f86SDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 24);
302*fcaf7f86SDimitry Andric 
303*fcaf7f86SDimitry Andric   Register SrcReg = MI.getOperand(3).getReg();
304*fcaf7f86SDimitry Andric   bool isKill = MI.getOperand(3).isKill();
305*fcaf7f86SDimitry Andric   // FIXME: it would be better to scavenge a register here instead of
306*fcaf7f86SDimitry Andric   // reserving SX16 all of the time.
307*fcaf7f86SDimitry Andric   Register TmpReg = VE::SX16;
308*fcaf7f86SDimitry Andric   for (int i = 0; i < 3; ++i) {
309*fcaf7f86SDimitry Andric     build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i);
310*fcaf7f86SDimitry Andric     MachineInstr *StMI =
311*fcaf7f86SDimitry Andric         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
312*fcaf7f86SDimitry Andric             TmpReg, getKillRegState(true));
313*fcaf7f86SDimitry Andric     replaceFI(*StMI, FrameReg, Offset, 0);
314*fcaf7f86SDimitry Andric     Offset += 8;
315*fcaf7f86SDimitry Andric   }
316*fcaf7f86SDimitry Andric   build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3);
317*fcaf7f86SDimitry Andric   MI.setDesc(get(VE::STrii));
318*fcaf7f86SDimitry Andric   MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
319*fcaf7f86SDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
320*fcaf7f86SDimitry Andric }
321*fcaf7f86SDimitry Andric 
322*fcaf7f86SDimitry Andric void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg,
323*fcaf7f86SDimitry Andric                                       int64_t Offset, int FIOperandNum) {
324*fcaf7f86SDimitry Andric   assert(MI.getOpcode() == VE::LDVMrii);
325*fcaf7f86SDimitry Andric   LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump());
326*fcaf7f86SDimitry Andric 
327*fcaf7f86SDimitry Andric   // Original MI is:
328*fcaf7f86SDimitry Andric   //   LDVMri reg, frame-index, 0, offset (, memory operand)
329*fcaf7f86SDimitry Andric   // Convert it to:
330*fcaf7f86SDimitry Andric   //   LDrii  tmp-reg, frame-reg, 0, offset
331*fcaf7f86SDimitry Andric   //   LVMir vm, 0, tmp-reg
332*fcaf7f86SDimitry Andric   //   LDrii  tmp-reg, frame-reg, 0, offset+8
333*fcaf7f86SDimitry Andric   //   LVMir_m vm, 1, tmp-reg, vm
334*fcaf7f86SDimitry Andric   //   LDrii  tmp-reg, frame-reg, 0, offset+16
335*fcaf7f86SDimitry Andric   //   LVMir_m vm, 2, tmp-reg, vm
336*fcaf7f86SDimitry Andric   //   LDrii  tmp-reg, frame-reg, 0, offset+24
337*fcaf7f86SDimitry Andric   //   LVMir_m vm, 3, tmp-reg, vm
338*fcaf7f86SDimitry Andric 
339*fcaf7f86SDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 24);
340*fcaf7f86SDimitry Andric 
341*fcaf7f86SDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
342*fcaf7f86SDimitry Andric   // FIXME: it would be better to scavenge a register here instead of
343*fcaf7f86SDimitry Andric   // reserving SX16 all of the time.
344*fcaf7f86SDimitry Andric   unsigned TmpReg = VE::SX16;
345*fcaf7f86SDimitry Andric   for (int i = 0; i < 4; ++i) {
346*fcaf7f86SDimitry Andric     if (i != 3) {
347*fcaf7f86SDimitry Andric       MachineInstr *StMI =
348*fcaf7f86SDimitry Andric           build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
349*fcaf7f86SDimitry Andric       replaceFI(*StMI, FrameReg, Offset, 1);
350*fcaf7f86SDimitry Andric       Offset += 8;
351*fcaf7f86SDimitry Andric     } else {
352*fcaf7f86SDimitry Andric       // Last LDrii replace the target instruction.
353*fcaf7f86SDimitry Andric       MI.setDesc(get(VE::LDrii));
354*fcaf7f86SDimitry Andric       MI.getOperand(0).ChangeToRegister(TmpReg, true);
355*fcaf7f86SDimitry Andric     }
356*fcaf7f86SDimitry Andric     // First LVM is LVMir.  Others are LVMir_m.  Last LVM places at the
357*fcaf7f86SDimitry Andric     // next of the target instruction.
358*fcaf7f86SDimitry Andric     if (i == 0)
359*fcaf7f86SDimitry Andric       build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true));
360*fcaf7f86SDimitry Andric     else if (i != 3)
361*fcaf7f86SDimitry Andric       build(VE::LVMir_m, DestReg)
362*fcaf7f86SDimitry Andric           .addImm(i)
363*fcaf7f86SDimitry Andric           .addReg(TmpReg, getKillRegState(true))
364*fcaf7f86SDimitry Andric           .addReg(DestReg);
365*fcaf7f86SDimitry Andric     else
366*fcaf7f86SDimitry Andric       BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg)
367*fcaf7f86SDimitry Andric           .addImm(3)
368*fcaf7f86SDimitry Andric           .addReg(TmpReg, getKillRegState(true))
369*fcaf7f86SDimitry Andric           .addReg(DestReg);
370*fcaf7f86SDimitry Andric   }
371*fcaf7f86SDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
372*fcaf7f86SDimitry Andric }
373*fcaf7f86SDimitry Andric 
374*fcaf7f86SDimitry Andric void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg,
375*fcaf7f86SDimitry Andric                                          int64_t Offset, int FIOperandNum) {
376*fcaf7f86SDimitry Andric   assert(MI.getOpcode() == VE::STVM512rii);
377*fcaf7f86SDimitry Andric   LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump());
378*fcaf7f86SDimitry Andric 
379*fcaf7f86SDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 56);
380*fcaf7f86SDimitry Andric 
381*fcaf7f86SDimitry Andric   Register SrcReg = MI.getOperand(3).getReg();
382*fcaf7f86SDimitry Andric   Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd);
383*fcaf7f86SDimitry Andric   Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even);
384*fcaf7f86SDimitry Andric   bool isKill = MI.getOperand(3).isKill();
385*fcaf7f86SDimitry Andric   // FIXME: it would be better to scavenge a register here instead of
386*fcaf7f86SDimitry Andric   // reserving SX16 all of the time.
387*fcaf7f86SDimitry Andric   Register TmpReg = VE::SX16;
388*fcaf7f86SDimitry Andric   // store low part of VMP
389*fcaf7f86SDimitry Andric   MachineInstr *LastMI = nullptr;
390*fcaf7f86SDimitry Andric   for (int i = 0; i < 4; ++i) {
391*fcaf7f86SDimitry Andric     LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i);
392*fcaf7f86SDimitry Andric     MachineInstr *StMI =
393*fcaf7f86SDimitry Andric         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
394*fcaf7f86SDimitry Andric             TmpReg, getKillRegState(true));
395*fcaf7f86SDimitry Andric     replaceFI(*StMI, FrameReg, Offset, 0);
396*fcaf7f86SDimitry Andric     Offset += 8;
397*fcaf7f86SDimitry Andric   }
398*fcaf7f86SDimitry Andric   if (isKill)
399*fcaf7f86SDimitry Andric     LastMI->addRegisterKilled(SrcLoReg, &TRI, true);
400*fcaf7f86SDimitry Andric   // store high part of VMP
401*fcaf7f86SDimitry Andric   for (int i = 0; i < 3; ++i) {
402*fcaf7f86SDimitry Andric     build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i);
403*fcaf7f86SDimitry Andric     MachineInstr *StMI =
404*fcaf7f86SDimitry Andric         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
405*fcaf7f86SDimitry Andric             TmpReg, getKillRegState(true));
406*fcaf7f86SDimitry Andric     replaceFI(*StMI, FrameReg, Offset, 0);
407*fcaf7f86SDimitry Andric     Offset += 8;
408*fcaf7f86SDimitry Andric   }
409*fcaf7f86SDimitry Andric   LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3);
410*fcaf7f86SDimitry Andric   if (isKill) {
411*fcaf7f86SDimitry Andric     LastMI->addRegisterKilled(SrcHiReg, &TRI, true);
412*fcaf7f86SDimitry Andric     // Add implicit super-register kills to the particular MI.
413*fcaf7f86SDimitry Andric     LastMI->addRegisterKilled(SrcReg, &TRI, true);
414*fcaf7f86SDimitry Andric   }
415*fcaf7f86SDimitry Andric   MI.setDesc(get(VE::STrii));
416*fcaf7f86SDimitry Andric   MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
417*fcaf7f86SDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
418*fcaf7f86SDimitry Andric }
419*fcaf7f86SDimitry Andric 
420*fcaf7f86SDimitry Andric void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg,
421*fcaf7f86SDimitry Andric                                          int64_t Offset, int FIOperandNum) {
422*fcaf7f86SDimitry Andric   assert(MI.getOpcode() == VE::LDVM512rii);
423*fcaf7f86SDimitry Andric   LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump());
424*fcaf7f86SDimitry Andric 
425*fcaf7f86SDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 56);
426*fcaf7f86SDimitry Andric 
427*fcaf7f86SDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
428*fcaf7f86SDimitry Andric   Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd);
429*fcaf7f86SDimitry Andric   Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even);
430*fcaf7f86SDimitry Andric   // FIXME: it would be better to scavenge a register here instead of
431*fcaf7f86SDimitry Andric   // reserving SX16 all of the time.
432*fcaf7f86SDimitry Andric   Register TmpReg = VE::SX16;
433*fcaf7f86SDimitry Andric   build(VE::IMPLICIT_DEF, DestReg);
434*fcaf7f86SDimitry Andric   for (int i = 0; i < 4; ++i) {
435*fcaf7f86SDimitry Andric     MachineInstr *LdMI =
436*fcaf7f86SDimitry Andric         build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
437*fcaf7f86SDimitry Andric     replaceFI(*LdMI, FrameReg, Offset, 1);
438*fcaf7f86SDimitry Andric     build(VE::LVMir_m, DestLoReg)
439*fcaf7f86SDimitry Andric         .addImm(i)
440*fcaf7f86SDimitry Andric         .addReg(TmpReg, getKillRegState(true))
441*fcaf7f86SDimitry Andric         .addReg(DestLoReg);
442*fcaf7f86SDimitry Andric     Offset += 8;
443*fcaf7f86SDimitry Andric   }
444*fcaf7f86SDimitry Andric   for (int i = 0; i < 3; ++i) {
445*fcaf7f86SDimitry Andric     MachineInstr *LdMI =
446*fcaf7f86SDimitry Andric         build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
447*fcaf7f86SDimitry Andric     replaceFI(*LdMI, FrameReg, Offset, 1);
448*fcaf7f86SDimitry Andric     build(VE::LVMir_m, DestHiReg)
449*fcaf7f86SDimitry Andric         .addImm(i)
450*fcaf7f86SDimitry Andric         .addReg(TmpReg, getKillRegState(true))
451*fcaf7f86SDimitry Andric         .addReg(DestHiReg);
452*fcaf7f86SDimitry Andric     Offset += 8;
453*fcaf7f86SDimitry Andric   }
454*fcaf7f86SDimitry Andric   MI.setDesc(get(VE::LDrii));
455*fcaf7f86SDimitry Andric   MI.getOperand(0).ChangeToRegister(TmpReg, true);
456*fcaf7f86SDimitry Andric   BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg)
457*fcaf7f86SDimitry Andric       .addImm(3)
458*fcaf7f86SDimitry Andric       .addReg(TmpReg, getKillRegState(true))
459*fcaf7f86SDimitry Andric       .addReg(DestHiReg);
460*fcaf7f86SDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
461*fcaf7f86SDimitry Andric }
462*fcaf7f86SDimitry Andric 
463753f127fSDimitry Andric void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,
464753f127fSDimitry Andric                                     int64_t Offset, int FIOperandNum) {
465753f127fSDimitry Andric   switch (MI.getOpcode()) {
466753f127fSDimitry Andric   case VE::STQrii:
467753f127fSDimitry Andric     processSTQ(MI, FrameReg, Offset, FIOperandNum);
468753f127fSDimitry Andric     return;
469753f127fSDimitry Andric   case VE::LDQrii:
470753f127fSDimitry Andric     processLDQ(MI, FrameReg, Offset, FIOperandNum);
471753f127fSDimitry Andric     return;
472*fcaf7f86SDimitry Andric   case VE::STVMrii:
473*fcaf7f86SDimitry Andric     processSTVM(MI, FrameReg, Offset, FIOperandNum);
474*fcaf7f86SDimitry Andric     return;
475*fcaf7f86SDimitry Andric   case VE::LDVMrii:
476*fcaf7f86SDimitry Andric     processLDVM(MI, FrameReg, Offset, FIOperandNum);
477*fcaf7f86SDimitry Andric     return;
478*fcaf7f86SDimitry Andric   case VE::STVM512rii:
479*fcaf7f86SDimitry Andric     processSTVM512(MI, FrameReg, Offset, FIOperandNum);
480*fcaf7f86SDimitry Andric     return;
481*fcaf7f86SDimitry Andric   case VE::LDVM512rii:
482*fcaf7f86SDimitry Andric     processLDVM512(MI, FrameReg, Offset, FIOperandNum);
483*fcaf7f86SDimitry Andric     return;
484753f127fSDimitry Andric   }
485753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset);
486753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
487753f127fSDimitry Andric }
488753f127fSDimitry Andric 
489480093f4SDimitry Andric void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
490480093f4SDimitry Andric                                          int SPAdj, unsigned FIOperandNum,
491480093f4SDimitry Andric                                          RegScavenger *RS) const {
492480093f4SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
493480093f4SDimitry Andric 
494480093f4SDimitry Andric   MachineInstr &MI = *II;
495480093f4SDimitry Andric   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
496753f127fSDimitry Andric 
497480093f4SDimitry Andric   MachineFunction &MF = *MI.getParent()->getParent();
498753f127fSDimitry Andric   const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
499753f127fSDimitry Andric   const VEFrameLowering &TFI = *getFrameLowering(MF);
500753f127fSDimitry Andric   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
501753f127fSDimitry Andric   const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();
502753f127fSDimitry Andric   DebugLoc DL = MI.getDebugLoc();
503753f127fSDimitry Andric   EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);
504480093f4SDimitry Andric 
505753f127fSDimitry Andric   // Retrieve FrameReg and byte offset for stack slot.
5065ffd83dbSDimitry Andric   Register FrameReg;
507753f127fSDimitry Andric   int64_t Offset =
508753f127fSDimitry Andric       TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
509e8d8bef9SDimitry Andric   Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
510e8d8bef9SDimitry Andric 
511753f127fSDimitry Andric   EFI.processMI(MI, FrameReg, Offset, FIOperandNum);
512480093f4SDimitry Andric }
513480093f4SDimitry Andric 
514480093f4SDimitry Andric Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
515480093f4SDimitry Andric   return VE::SX9;
516480093f4SDimitry Andric }
517