xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/VE/VERegisterInfo.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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
VERegisterInfo()36480093f4SDimitry Andric VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}
37480093f4SDimitry Andric 
38480093f4SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const39480093f4SDimitry 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 
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const50480093f4SDimitry 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 
getNoPreservedMask() const62480093f4SDimitry Andric const uint32_t *VERegisterInfo::getNoPreservedMask() const {
63480093f4SDimitry Andric   return CSR_NoRegs_RegMask;
64480093f4SDimitry Andric }
65480093f4SDimitry Andric 
getReservedRegs(const MachineFunction & MF) const66480093f4SDimitry 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 
99480093f4SDimitry Andric const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const100480093f4SDimitry Andric VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
101480093f4SDimitry Andric                                    unsigned Kind) const {
102480093f4SDimitry Andric   return &VE::I64RegClass;
103480093f4SDimitry Andric }
104480093f4SDimitry Andric 
offsetToDisp(MachineInstr & MI)105e8d8bef9SDimitry Andric static unsigned offsetToDisp(MachineInstr &MI) {
106e8d8bef9SDimitry Andric   // Default offset in instruction's operands (reg+reg+imm).
107e8d8bef9SDimitry Andric   unsigned OffDisp = 2;
108e8d8bef9SDimitry Andric 
109e8d8bef9SDimitry Andric #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
110e8d8bef9SDimitry Andric 
111e8d8bef9SDimitry Andric   {
112e8d8bef9SDimitry Andric     using namespace llvm::VE;
113e8d8bef9SDimitry Andric     switch (MI.getOpcode()) {
114*bdd1243dSDimitry Andric     case INLINEASM:
115e8d8bef9SDimitry Andric     case RRCAS_multi_cases(TS1AML):
116e8d8bef9SDimitry Andric     case RRCAS_multi_cases(TS1AMW):
117e8d8bef9SDimitry Andric     case RRCAS_multi_cases(CASL):
118e8d8bef9SDimitry Andric     case RRCAS_multi_cases(CASW):
119e8d8bef9SDimitry Andric       // These instructions use AS format (reg+imm).
120e8d8bef9SDimitry Andric       OffDisp = 1;
121e8d8bef9SDimitry Andric       break;
122e8d8bef9SDimitry Andric     }
123e8d8bef9SDimitry Andric   }
124e8d8bef9SDimitry Andric #undef RRCAS_multi_cases
125e8d8bef9SDimitry Andric 
126e8d8bef9SDimitry Andric   return OffDisp;
127e8d8bef9SDimitry Andric }
128e8d8bef9SDimitry Andric 
129*bdd1243dSDimitry Andric namespace {
130753f127fSDimitry Andric class EliminateFrameIndex {
131753f127fSDimitry Andric   const TargetInstrInfo &TII;
132753f127fSDimitry Andric   const TargetRegisterInfo &TRI;
133753f127fSDimitry Andric   const DebugLoc &DL;
134753f127fSDimitry Andric   MachineBasicBlock &MBB;
135753f127fSDimitry Andric   MachineBasicBlock::iterator II;
136753f127fSDimitry Andric   Register clobber;
137753f127fSDimitry Andric 
138753f127fSDimitry Andric   // Some helper functions for the ease of instruction building.
getFunc() const139753f127fSDimitry Andric   MachineFunction &getFunc() const { return *MBB.getParent(); }
getSubReg(MCRegister Reg,unsigned Idx) const140753f127fSDimitry Andric   inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {
141753f127fSDimitry Andric     return TRI.getSubReg(Reg, Idx);
142753f127fSDimitry Andric   }
get(unsigned Opcode) const143753f127fSDimitry Andric   inline const MCInstrDesc &get(unsigned Opcode) const {
144753f127fSDimitry Andric     return TII.get(Opcode);
145753f127fSDimitry Andric   }
build(const MCInstrDesc & MCID,Register DestReg)146753f127fSDimitry Andric   inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {
147753f127fSDimitry Andric     return BuildMI(MBB, II, DL, MCID, DestReg);
148753f127fSDimitry Andric   }
build(unsigned InstOpc,Register DestReg)149753f127fSDimitry Andric   inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {
150753f127fSDimitry Andric     return build(get(InstOpc), DestReg);
151753f127fSDimitry Andric   }
build(const MCInstrDesc & MCID)152753f127fSDimitry Andric   inline MachineInstrBuilder build(const MCInstrDesc &MCID) {
153753f127fSDimitry Andric     return BuildMI(MBB, II, DL, MCID);
154753f127fSDimitry Andric   }
build(unsigned InstOpc)155753f127fSDimitry Andric   inline MachineInstrBuilder build(unsigned InstOpc) {
156753f127fSDimitry Andric     return build(get(InstOpc));
157753f127fSDimitry Andric   }
158753f127fSDimitry Andric 
159753f127fSDimitry Andric   // Calculate an address of frame index from a frame register and a given
160753f127fSDimitry Andric   // offset if the offset doesn't fit in the immediate field.  Use a clobber
161753f127fSDimitry Andric   // register to hold calculated address.
162753f127fSDimitry Andric   void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,
163753f127fSDimitry Andric                         int64_t Bytes = 0);
164753f127fSDimitry Andric   // Replace the frame index in \p MI with a frame register and a given offset
165753f127fSDimitry Andric   // if it fits in the immediate field.  Otherwise, use pre-calculated address
166753f127fSDimitry Andric   // in a clobber regsiter.
167753f127fSDimitry Andric   void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,
168753f127fSDimitry Andric                  int FIOperandNum);
169753f127fSDimitry Andric 
170753f127fSDimitry Andric   // Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
171753f127fSDimitry Andric   void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
172753f127fSDimitry Andric                   int FIOperandNum);
173753f127fSDimitry Andric   void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
174753f127fSDimitry Andric                   int FIOperandNum);
175fcaf7f86SDimitry Andric   // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.
176fcaf7f86SDimitry Andric   void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
177fcaf7f86SDimitry Andric                    int FIOperandNum);
178fcaf7f86SDimitry Andric   void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
179fcaf7f86SDimitry Andric                    int FIOperandNum);
180fcaf7f86SDimitry Andric   // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.
181fcaf7f86SDimitry Andric   void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
182fcaf7f86SDimitry Andric                       int FIOperandNum);
183fcaf7f86SDimitry Andric   void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
184fcaf7f86SDimitry Andric                       int FIOperandNum);
185753f127fSDimitry Andric 
186753f127fSDimitry Andric public:
EliminateFrameIndex(const TargetInstrInfo & TII,const TargetRegisterInfo & TRI,const DebugLoc & DL,MachineBasicBlock & MBB,MachineBasicBlock::iterator II)187753f127fSDimitry Andric   EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
188753f127fSDimitry Andric                       const DebugLoc &DL, MachineBasicBlock &MBB,
189753f127fSDimitry Andric                       MachineBasicBlock::iterator II)
190753f127fSDimitry Andric       : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}
191753f127fSDimitry Andric 
192753f127fSDimitry Andric   // Expand and eliminate Frame Index from MI
193753f127fSDimitry Andric   void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,
194753f127fSDimitry Andric                  int FIOperandNum);
195753f127fSDimitry Andric };
196*bdd1243dSDimitry Andric } // namespace
197753f127fSDimitry Andric 
198753f127fSDimitry Andric // Prepare the frame index if it doesn't fit in the immediate field.  Use
199753f127fSDimitry Andric // clobber register to hold calculated address.
prepareReplaceFI(MachineInstr & MI,Register & FrameReg,int64_t & Offset,int64_t Bytes)200753f127fSDimitry Andric void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,
201753f127fSDimitry Andric                                            int64_t &Offset, int64_t Bytes) {
202753f127fSDimitry Andric   if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {
203753f127fSDimitry Andric     // If the offset is small enough to fit in the immediate field, directly
204753f127fSDimitry Andric     // encode it.  So, nothing to prepare here.
205753f127fSDimitry Andric     return;
206753f127fSDimitry Andric   }
207753f127fSDimitry Andric 
208753f127fSDimitry Andric   // If the offset doesn't fit, emit following codes.  This clobbers SX13
209753f127fSDimitry Andric   // which we always know is available here.
210753f127fSDimitry Andric   //   lea     %clobber, Offset@lo
211753f127fSDimitry Andric   //   and     %clobber, %clobber, (32)0
212753f127fSDimitry Andric   //   lea.sl  %clobber, Offset@hi(FrameReg, %clobber)
213753f127fSDimitry Andric   build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));
214753f127fSDimitry Andric   build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));
215753f127fSDimitry Andric   build(VE::LEASLrri, clobber)
216753f127fSDimitry Andric       .addReg(clobber)
217753f127fSDimitry Andric       .addReg(FrameReg)
218753f127fSDimitry Andric       .addImm(Hi_32(Offset));
219753f127fSDimitry Andric 
220753f127fSDimitry Andric   // Use clobber register as a frame register and 0 offset
221753f127fSDimitry Andric   FrameReg = clobber;
222753f127fSDimitry Andric   Offset = 0;
223753f127fSDimitry Andric }
224753f127fSDimitry Andric 
225753f127fSDimitry Andric // Replace the frame index in \p MI with a proper byte and framereg offset.
replaceFI(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)226753f127fSDimitry Andric void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,
227753f127fSDimitry Andric                                     int64_t Offset, int FIOperandNum) {
228753f127fSDimitry Andric   assert(isInt<32>(Offset));
229753f127fSDimitry Andric 
230753f127fSDimitry Andric   // The offset must be small enough to fit in the immediate field after
231753f127fSDimitry Andric   // call of prepareReplaceFI.  Therefore, we directly encode it.
2325ffd83dbSDimitry Andric   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
233e8d8bef9SDimitry Andric   MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
234480093f4SDimitry Andric }
235480093f4SDimitry Andric 
processSTQ(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)236753f127fSDimitry Andric void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,
237753f127fSDimitry Andric                                      int64_t Offset, int FIOperandNum) {
238753f127fSDimitry Andric   assert(MI.getOpcode() == VE::STQrii);
239753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());
240753f127fSDimitry Andric 
241753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 8);
242753f127fSDimitry Andric 
243753f127fSDimitry Andric   Register SrcReg = MI.getOperand(3).getReg();
244753f127fSDimitry Andric   Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
245753f127fSDimitry Andric   Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
246753f127fSDimitry Andric   // VE stores HiReg to 8(addr) and LoReg to 0(addr)
247753f127fSDimitry Andric   MachineInstr *StMI =
248753f127fSDimitry Andric       build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);
249753f127fSDimitry Andric   replaceFI(*StMI, FrameReg, Offset, 0);
250753f127fSDimitry Andric   // Mutate to 'hi' store.
251753f127fSDimitry Andric   MI.setDesc(get(VE::STrii));
252753f127fSDimitry Andric   MI.getOperand(3).setReg(SrcHiReg);
253753f127fSDimitry Andric   Offset += 8;
254753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
255753f127fSDimitry Andric }
256753f127fSDimitry Andric 
processLDQ(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)257753f127fSDimitry Andric void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,
258753f127fSDimitry Andric                                      int64_t Offset, int FIOperandNum) {
259753f127fSDimitry Andric   assert(MI.getOpcode() == VE::LDQrii);
260753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());
261753f127fSDimitry Andric 
262753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 8);
263753f127fSDimitry Andric 
264753f127fSDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
265753f127fSDimitry Andric   Register DestHiReg = getSubReg(DestReg, VE::sub_even);
266753f127fSDimitry Andric   Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
267753f127fSDimitry Andric   // VE loads HiReg from 8(addr) and LoReg from 0(addr)
268753f127fSDimitry Andric   MachineInstr *StMI =
269753f127fSDimitry Andric       build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);
270753f127fSDimitry Andric   replaceFI(*StMI, FrameReg, Offset, 1);
271753f127fSDimitry Andric   MI.setDesc(get(VE::LDrii));
272753f127fSDimitry Andric   MI.getOperand(0).setReg(DestHiReg);
273753f127fSDimitry Andric   Offset += 8;
274753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
275753f127fSDimitry Andric }
276753f127fSDimitry Andric 
processSTVM(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)277fcaf7f86SDimitry Andric void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg,
278fcaf7f86SDimitry Andric                                       int64_t Offset, int FIOperandNum) {
279fcaf7f86SDimitry Andric   assert(MI.getOpcode() == VE::STVMrii);
280fcaf7f86SDimitry Andric   LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump());
281fcaf7f86SDimitry Andric 
282fcaf7f86SDimitry Andric   // Original MI is:
283fcaf7f86SDimitry Andric   //   STVMrii frame-index, 0, offset, reg (, memory operand)
284fcaf7f86SDimitry Andric   // Convert it to:
285fcaf7f86SDimitry Andric   //   SVMi   tmp-reg, reg, 0
286fcaf7f86SDimitry Andric   //   STrii  frame-reg, 0, offset, tmp-reg
287fcaf7f86SDimitry Andric   //   SVMi   tmp-reg, reg, 1
288fcaf7f86SDimitry Andric   //   STrii  frame-reg, 0, offset+8, tmp-reg
289fcaf7f86SDimitry Andric   //   SVMi   tmp-reg, reg, 2
290fcaf7f86SDimitry Andric   //   STrii  frame-reg, 0, offset+16, tmp-reg
291fcaf7f86SDimitry Andric   //   SVMi   tmp-reg, reg, 3
292fcaf7f86SDimitry Andric   //   STrii  frame-reg, 0, offset+24, tmp-reg
293fcaf7f86SDimitry Andric 
294fcaf7f86SDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 24);
295fcaf7f86SDimitry Andric 
296fcaf7f86SDimitry Andric   Register SrcReg = MI.getOperand(3).getReg();
297fcaf7f86SDimitry Andric   bool isKill = MI.getOperand(3).isKill();
298fcaf7f86SDimitry Andric   // FIXME: it would be better to scavenge a register here instead of
299fcaf7f86SDimitry Andric   // reserving SX16 all of the time.
300fcaf7f86SDimitry Andric   Register TmpReg = VE::SX16;
301fcaf7f86SDimitry Andric   for (int i = 0; i < 3; ++i) {
302fcaf7f86SDimitry Andric     build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i);
303fcaf7f86SDimitry Andric     MachineInstr *StMI =
304fcaf7f86SDimitry Andric         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
305fcaf7f86SDimitry Andric             TmpReg, getKillRegState(true));
306fcaf7f86SDimitry Andric     replaceFI(*StMI, FrameReg, Offset, 0);
307fcaf7f86SDimitry Andric     Offset += 8;
308fcaf7f86SDimitry Andric   }
309fcaf7f86SDimitry Andric   build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3);
310fcaf7f86SDimitry Andric   MI.setDesc(get(VE::STrii));
311fcaf7f86SDimitry Andric   MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
312fcaf7f86SDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
313fcaf7f86SDimitry Andric }
314fcaf7f86SDimitry Andric 
processLDVM(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)315fcaf7f86SDimitry Andric void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg,
316fcaf7f86SDimitry Andric                                       int64_t Offset, int FIOperandNum) {
317fcaf7f86SDimitry Andric   assert(MI.getOpcode() == VE::LDVMrii);
318fcaf7f86SDimitry Andric   LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump());
319fcaf7f86SDimitry Andric 
320fcaf7f86SDimitry Andric   // Original MI is:
321fcaf7f86SDimitry Andric   //   LDVMri reg, frame-index, 0, offset (, memory operand)
322fcaf7f86SDimitry Andric   // Convert it to:
323fcaf7f86SDimitry Andric   //   LDrii  tmp-reg, frame-reg, 0, offset
324fcaf7f86SDimitry Andric   //   LVMir vm, 0, tmp-reg
325fcaf7f86SDimitry Andric   //   LDrii  tmp-reg, frame-reg, 0, offset+8
326fcaf7f86SDimitry Andric   //   LVMir_m vm, 1, tmp-reg, vm
327fcaf7f86SDimitry Andric   //   LDrii  tmp-reg, frame-reg, 0, offset+16
328fcaf7f86SDimitry Andric   //   LVMir_m vm, 2, tmp-reg, vm
329fcaf7f86SDimitry Andric   //   LDrii  tmp-reg, frame-reg, 0, offset+24
330fcaf7f86SDimitry Andric   //   LVMir_m vm, 3, tmp-reg, vm
331fcaf7f86SDimitry Andric 
332fcaf7f86SDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 24);
333fcaf7f86SDimitry Andric 
334fcaf7f86SDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
335fcaf7f86SDimitry Andric   // FIXME: it would be better to scavenge a register here instead of
336fcaf7f86SDimitry Andric   // reserving SX16 all of the time.
337fcaf7f86SDimitry Andric   unsigned TmpReg = VE::SX16;
338fcaf7f86SDimitry Andric   for (int i = 0; i < 4; ++i) {
339fcaf7f86SDimitry Andric     if (i != 3) {
340fcaf7f86SDimitry Andric       MachineInstr *StMI =
341fcaf7f86SDimitry Andric           build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
342fcaf7f86SDimitry Andric       replaceFI(*StMI, FrameReg, Offset, 1);
343fcaf7f86SDimitry Andric       Offset += 8;
344fcaf7f86SDimitry Andric     } else {
345fcaf7f86SDimitry Andric       // Last LDrii replace the target instruction.
346fcaf7f86SDimitry Andric       MI.setDesc(get(VE::LDrii));
347fcaf7f86SDimitry Andric       MI.getOperand(0).ChangeToRegister(TmpReg, true);
348fcaf7f86SDimitry Andric     }
349fcaf7f86SDimitry Andric     // First LVM is LVMir.  Others are LVMir_m.  Last LVM places at the
350fcaf7f86SDimitry Andric     // next of the target instruction.
351fcaf7f86SDimitry Andric     if (i == 0)
352fcaf7f86SDimitry Andric       build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true));
353fcaf7f86SDimitry Andric     else if (i != 3)
354fcaf7f86SDimitry Andric       build(VE::LVMir_m, DestReg)
355fcaf7f86SDimitry Andric           .addImm(i)
356fcaf7f86SDimitry Andric           .addReg(TmpReg, getKillRegState(true))
357fcaf7f86SDimitry Andric           .addReg(DestReg);
358fcaf7f86SDimitry Andric     else
359fcaf7f86SDimitry Andric       BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg)
360fcaf7f86SDimitry Andric           .addImm(3)
361fcaf7f86SDimitry Andric           .addReg(TmpReg, getKillRegState(true))
362fcaf7f86SDimitry Andric           .addReg(DestReg);
363fcaf7f86SDimitry Andric   }
364fcaf7f86SDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
365fcaf7f86SDimitry Andric }
366fcaf7f86SDimitry Andric 
processSTVM512(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)367fcaf7f86SDimitry Andric void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg,
368fcaf7f86SDimitry Andric                                          int64_t Offset, int FIOperandNum) {
369fcaf7f86SDimitry Andric   assert(MI.getOpcode() == VE::STVM512rii);
370fcaf7f86SDimitry Andric   LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump());
371fcaf7f86SDimitry Andric 
372fcaf7f86SDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 56);
373fcaf7f86SDimitry Andric 
374fcaf7f86SDimitry Andric   Register SrcReg = MI.getOperand(3).getReg();
375fcaf7f86SDimitry Andric   Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd);
376fcaf7f86SDimitry Andric   Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even);
377fcaf7f86SDimitry Andric   bool isKill = MI.getOperand(3).isKill();
378fcaf7f86SDimitry Andric   // FIXME: it would be better to scavenge a register here instead of
379fcaf7f86SDimitry Andric   // reserving SX16 all of the time.
380fcaf7f86SDimitry Andric   Register TmpReg = VE::SX16;
381fcaf7f86SDimitry Andric   // store low part of VMP
382fcaf7f86SDimitry Andric   MachineInstr *LastMI = nullptr;
383fcaf7f86SDimitry Andric   for (int i = 0; i < 4; ++i) {
384fcaf7f86SDimitry Andric     LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i);
385fcaf7f86SDimitry Andric     MachineInstr *StMI =
386fcaf7f86SDimitry Andric         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
387fcaf7f86SDimitry Andric             TmpReg, getKillRegState(true));
388fcaf7f86SDimitry Andric     replaceFI(*StMI, FrameReg, Offset, 0);
389fcaf7f86SDimitry Andric     Offset += 8;
390fcaf7f86SDimitry Andric   }
391fcaf7f86SDimitry Andric   if (isKill)
392fcaf7f86SDimitry Andric     LastMI->addRegisterKilled(SrcLoReg, &TRI, true);
393fcaf7f86SDimitry Andric   // store high part of VMP
394fcaf7f86SDimitry Andric   for (int i = 0; i < 3; ++i) {
395fcaf7f86SDimitry Andric     build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i);
396fcaf7f86SDimitry Andric     MachineInstr *StMI =
397fcaf7f86SDimitry Andric         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
398fcaf7f86SDimitry Andric             TmpReg, getKillRegState(true));
399fcaf7f86SDimitry Andric     replaceFI(*StMI, FrameReg, Offset, 0);
400fcaf7f86SDimitry Andric     Offset += 8;
401fcaf7f86SDimitry Andric   }
402fcaf7f86SDimitry Andric   LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3);
403fcaf7f86SDimitry Andric   if (isKill) {
404fcaf7f86SDimitry Andric     LastMI->addRegisterKilled(SrcHiReg, &TRI, true);
405fcaf7f86SDimitry Andric     // Add implicit super-register kills to the particular MI.
406fcaf7f86SDimitry Andric     LastMI->addRegisterKilled(SrcReg, &TRI, true);
407fcaf7f86SDimitry Andric   }
408fcaf7f86SDimitry Andric   MI.setDesc(get(VE::STrii));
409fcaf7f86SDimitry Andric   MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
410fcaf7f86SDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
411fcaf7f86SDimitry Andric }
412fcaf7f86SDimitry Andric 
processLDVM512(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)413fcaf7f86SDimitry Andric void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg,
414fcaf7f86SDimitry Andric                                          int64_t Offset, int FIOperandNum) {
415fcaf7f86SDimitry Andric   assert(MI.getOpcode() == VE::LDVM512rii);
416fcaf7f86SDimitry Andric   LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump());
417fcaf7f86SDimitry Andric 
418fcaf7f86SDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 56);
419fcaf7f86SDimitry Andric 
420fcaf7f86SDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
421fcaf7f86SDimitry Andric   Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd);
422fcaf7f86SDimitry Andric   Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even);
423fcaf7f86SDimitry Andric   // FIXME: it would be better to scavenge a register here instead of
424fcaf7f86SDimitry Andric   // reserving SX16 all of the time.
425fcaf7f86SDimitry Andric   Register TmpReg = VE::SX16;
426fcaf7f86SDimitry Andric   build(VE::IMPLICIT_DEF, DestReg);
427fcaf7f86SDimitry Andric   for (int i = 0; i < 4; ++i) {
428fcaf7f86SDimitry Andric     MachineInstr *LdMI =
429fcaf7f86SDimitry Andric         build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
430fcaf7f86SDimitry Andric     replaceFI(*LdMI, FrameReg, Offset, 1);
431fcaf7f86SDimitry Andric     build(VE::LVMir_m, DestLoReg)
432fcaf7f86SDimitry Andric         .addImm(i)
433fcaf7f86SDimitry Andric         .addReg(TmpReg, getKillRegState(true))
434fcaf7f86SDimitry Andric         .addReg(DestLoReg);
435fcaf7f86SDimitry Andric     Offset += 8;
436fcaf7f86SDimitry Andric   }
437fcaf7f86SDimitry Andric   for (int i = 0; i < 3; ++i) {
438fcaf7f86SDimitry Andric     MachineInstr *LdMI =
439fcaf7f86SDimitry Andric         build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
440fcaf7f86SDimitry Andric     replaceFI(*LdMI, FrameReg, Offset, 1);
441fcaf7f86SDimitry Andric     build(VE::LVMir_m, DestHiReg)
442fcaf7f86SDimitry Andric         .addImm(i)
443fcaf7f86SDimitry Andric         .addReg(TmpReg, getKillRegState(true))
444fcaf7f86SDimitry Andric         .addReg(DestHiReg);
445fcaf7f86SDimitry Andric     Offset += 8;
446fcaf7f86SDimitry Andric   }
447fcaf7f86SDimitry Andric   MI.setDesc(get(VE::LDrii));
448fcaf7f86SDimitry Andric   MI.getOperand(0).ChangeToRegister(TmpReg, true);
449fcaf7f86SDimitry Andric   BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg)
450fcaf7f86SDimitry Andric       .addImm(3)
451fcaf7f86SDimitry Andric       .addReg(TmpReg, getKillRegState(true))
452fcaf7f86SDimitry Andric       .addReg(DestHiReg);
453fcaf7f86SDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
454fcaf7f86SDimitry Andric }
455fcaf7f86SDimitry Andric 
processMI(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)456753f127fSDimitry Andric void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,
457753f127fSDimitry Andric                                     int64_t Offset, int FIOperandNum) {
458753f127fSDimitry Andric   switch (MI.getOpcode()) {
459753f127fSDimitry Andric   case VE::STQrii:
460753f127fSDimitry Andric     processSTQ(MI, FrameReg, Offset, FIOperandNum);
461753f127fSDimitry Andric     return;
462753f127fSDimitry Andric   case VE::LDQrii:
463753f127fSDimitry Andric     processLDQ(MI, FrameReg, Offset, FIOperandNum);
464753f127fSDimitry Andric     return;
465fcaf7f86SDimitry Andric   case VE::STVMrii:
466fcaf7f86SDimitry Andric     processSTVM(MI, FrameReg, Offset, FIOperandNum);
467fcaf7f86SDimitry Andric     return;
468fcaf7f86SDimitry Andric   case VE::LDVMrii:
469fcaf7f86SDimitry Andric     processLDVM(MI, FrameReg, Offset, FIOperandNum);
470fcaf7f86SDimitry Andric     return;
471fcaf7f86SDimitry Andric   case VE::STVM512rii:
472fcaf7f86SDimitry Andric     processSTVM512(MI, FrameReg, Offset, FIOperandNum);
473fcaf7f86SDimitry Andric     return;
474fcaf7f86SDimitry Andric   case VE::LDVM512rii:
475fcaf7f86SDimitry Andric     processLDVM512(MI, FrameReg, Offset, FIOperandNum);
476fcaf7f86SDimitry Andric     return;
477753f127fSDimitry Andric   }
478753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset);
479753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
480753f127fSDimitry Andric }
481753f127fSDimitry Andric 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const482*bdd1243dSDimitry Andric bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
483480093f4SDimitry Andric                                          int SPAdj, unsigned FIOperandNum,
484480093f4SDimitry Andric                                          RegScavenger *RS) const {
485480093f4SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
486480093f4SDimitry Andric 
487480093f4SDimitry Andric   MachineInstr &MI = *II;
488480093f4SDimitry Andric   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
489753f127fSDimitry Andric 
490480093f4SDimitry Andric   MachineFunction &MF = *MI.getParent()->getParent();
491753f127fSDimitry Andric   const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
492753f127fSDimitry Andric   const VEFrameLowering &TFI = *getFrameLowering(MF);
493753f127fSDimitry Andric   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
494753f127fSDimitry Andric   const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();
495753f127fSDimitry Andric   DebugLoc DL = MI.getDebugLoc();
496753f127fSDimitry Andric   EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);
497480093f4SDimitry Andric 
498753f127fSDimitry Andric   // Retrieve FrameReg and byte offset for stack slot.
4995ffd83dbSDimitry Andric   Register FrameReg;
500753f127fSDimitry Andric   int64_t Offset =
501753f127fSDimitry Andric       TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
502e8d8bef9SDimitry Andric   Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
503e8d8bef9SDimitry Andric 
504753f127fSDimitry Andric   EFI.processMI(MI, FrameReg, Offset, FIOperandNum);
505*bdd1243dSDimitry Andric   return false;
506480093f4SDimitry Andric }
507480093f4SDimitry Andric 
getFrameRegister(const MachineFunction & MF) const508480093f4SDimitry Andric Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
509480093f4SDimitry Andric   return VE::SX9;
510480093f4SDimitry Andric }
511