xref: /freebsd/contrib/llvm-project/llvm/lib/Target/VE/VERegisterInfo.cpp (revision 753f127f3ace09432b2baeffd71a308760641a62)
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 
30*753f127fSDimitry Andric #define DEBUG_TYPE "ve-register-info"
31*753f127fSDimitry 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 
138*753f127fSDimitry Andric class EliminateFrameIndex {
139*753f127fSDimitry Andric   const TargetInstrInfo &TII;
140*753f127fSDimitry Andric   const TargetRegisterInfo &TRI;
141*753f127fSDimitry Andric   const DebugLoc &DL;
142*753f127fSDimitry Andric   MachineBasicBlock &MBB;
143*753f127fSDimitry Andric   MachineBasicBlock::iterator II;
144*753f127fSDimitry Andric   Register clobber;
145*753f127fSDimitry Andric 
146*753f127fSDimitry Andric   // Some helper functions for the ease of instruction building.
147*753f127fSDimitry Andric   MachineFunction &getFunc() const { return *MBB.getParent(); }
148*753f127fSDimitry Andric   inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {
149*753f127fSDimitry Andric     return TRI.getSubReg(Reg, Idx);
150*753f127fSDimitry Andric   }
151*753f127fSDimitry Andric   inline const MCInstrDesc &get(unsigned Opcode) const {
152*753f127fSDimitry Andric     return TII.get(Opcode);
153*753f127fSDimitry Andric   }
154*753f127fSDimitry Andric   inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {
155*753f127fSDimitry Andric     return BuildMI(MBB, II, DL, MCID, DestReg);
156*753f127fSDimitry Andric   }
157*753f127fSDimitry Andric   inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {
158*753f127fSDimitry Andric     return build(get(InstOpc), DestReg);
159*753f127fSDimitry Andric   }
160*753f127fSDimitry Andric   inline MachineInstrBuilder build(const MCInstrDesc &MCID) {
161*753f127fSDimitry Andric     return BuildMI(MBB, II, DL, MCID);
162*753f127fSDimitry Andric   }
163*753f127fSDimitry Andric   inline MachineInstrBuilder build(unsigned InstOpc) {
164*753f127fSDimitry Andric     return build(get(InstOpc));
165*753f127fSDimitry Andric   }
166*753f127fSDimitry Andric 
167*753f127fSDimitry Andric   // Calculate an address of frame index from a frame register and a given
168*753f127fSDimitry Andric   // offset if the offset doesn't fit in the immediate field.  Use a clobber
169*753f127fSDimitry Andric   // register to hold calculated address.
170*753f127fSDimitry Andric   void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,
171*753f127fSDimitry Andric                         int64_t Bytes = 0);
172*753f127fSDimitry Andric   // Replace the frame index in \p MI with a frame register and a given offset
173*753f127fSDimitry Andric   // if it fits in the immediate field.  Otherwise, use pre-calculated address
174*753f127fSDimitry Andric   // in a clobber regsiter.
175*753f127fSDimitry Andric   void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,
176*753f127fSDimitry Andric                  int FIOperandNum);
177*753f127fSDimitry Andric 
178*753f127fSDimitry Andric   // Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
179*753f127fSDimitry Andric   void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
180*753f127fSDimitry Andric                   int FIOperandNum);
181*753f127fSDimitry Andric   void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
182*753f127fSDimitry Andric                   int FIOperandNum);
183*753f127fSDimitry Andric 
184*753f127fSDimitry Andric public:
185*753f127fSDimitry Andric   EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
186*753f127fSDimitry Andric                       const DebugLoc &DL, MachineBasicBlock &MBB,
187*753f127fSDimitry Andric                       MachineBasicBlock::iterator II)
188*753f127fSDimitry Andric       : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}
189*753f127fSDimitry Andric 
190*753f127fSDimitry Andric   // Expand and eliminate Frame Index from MI
191*753f127fSDimitry Andric   void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,
192*753f127fSDimitry Andric                  int FIOperandNum);
193*753f127fSDimitry Andric };
194*753f127fSDimitry Andric 
195*753f127fSDimitry Andric // Prepare the frame index if it doesn't fit in the immediate field.  Use
196*753f127fSDimitry Andric // clobber register to hold calculated address.
197*753f127fSDimitry Andric void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,
198*753f127fSDimitry Andric                                            int64_t &Offset, int64_t Bytes) {
199*753f127fSDimitry Andric   if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {
200*753f127fSDimitry Andric     // If the offset is small enough to fit in the immediate field, directly
201*753f127fSDimitry Andric     // encode it.  So, nothing to prepare here.
202*753f127fSDimitry Andric     return;
203*753f127fSDimitry Andric   }
204*753f127fSDimitry Andric 
205*753f127fSDimitry Andric   // If the offset doesn't fit, emit following codes.  This clobbers SX13
206*753f127fSDimitry Andric   // which we always know is available here.
207*753f127fSDimitry Andric   //   lea     %clobber, Offset@lo
208*753f127fSDimitry Andric   //   and     %clobber, %clobber, (32)0
209*753f127fSDimitry Andric   //   lea.sl  %clobber, Offset@hi(FrameReg, %clobber)
210*753f127fSDimitry Andric   build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));
211*753f127fSDimitry Andric   build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));
212*753f127fSDimitry Andric   build(VE::LEASLrri, clobber)
213*753f127fSDimitry Andric       .addReg(clobber)
214*753f127fSDimitry Andric       .addReg(FrameReg)
215*753f127fSDimitry Andric       .addImm(Hi_32(Offset));
216*753f127fSDimitry Andric 
217*753f127fSDimitry Andric   // Use clobber register as a frame register and 0 offset
218*753f127fSDimitry Andric   FrameReg = clobber;
219*753f127fSDimitry Andric   Offset = 0;
220*753f127fSDimitry Andric }
221*753f127fSDimitry Andric 
222*753f127fSDimitry Andric // Replace the frame index in \p MI with a proper byte and framereg offset.
223*753f127fSDimitry Andric void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,
224*753f127fSDimitry Andric                                     int64_t Offset, int FIOperandNum) {
225*753f127fSDimitry Andric   assert(isInt<32>(Offset));
226*753f127fSDimitry Andric 
227*753f127fSDimitry Andric   // The offset must be small enough to fit in the immediate field after
228*753f127fSDimitry Andric   // call of prepareReplaceFI.  Therefore, we directly encode it.
2295ffd83dbSDimitry Andric   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
230e8d8bef9SDimitry Andric   MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
231480093f4SDimitry Andric }
232480093f4SDimitry Andric 
233*753f127fSDimitry Andric void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,
234*753f127fSDimitry Andric                                      int64_t Offset, int FIOperandNum) {
235*753f127fSDimitry Andric   assert(MI.getOpcode() == VE::STQrii);
236*753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());
237*753f127fSDimitry Andric 
238*753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 8);
239*753f127fSDimitry Andric 
240*753f127fSDimitry Andric   Register SrcReg = MI.getOperand(3).getReg();
241*753f127fSDimitry Andric   Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
242*753f127fSDimitry Andric   Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
243*753f127fSDimitry Andric   // VE stores HiReg to 8(addr) and LoReg to 0(addr)
244*753f127fSDimitry Andric   MachineInstr *StMI =
245*753f127fSDimitry Andric       build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);
246*753f127fSDimitry Andric   replaceFI(*StMI, FrameReg, Offset, 0);
247*753f127fSDimitry Andric   // Mutate to 'hi' store.
248*753f127fSDimitry Andric   MI.setDesc(get(VE::STrii));
249*753f127fSDimitry Andric   MI.getOperand(3).setReg(SrcHiReg);
250*753f127fSDimitry Andric   Offset += 8;
251*753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
252*753f127fSDimitry Andric }
253*753f127fSDimitry Andric 
254*753f127fSDimitry Andric void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,
255*753f127fSDimitry Andric                                      int64_t Offset, int FIOperandNum) {
256*753f127fSDimitry Andric   assert(MI.getOpcode() == VE::LDQrii);
257*753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());
258*753f127fSDimitry Andric 
259*753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset, 8);
260*753f127fSDimitry Andric 
261*753f127fSDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
262*753f127fSDimitry Andric   Register DestHiReg = getSubReg(DestReg, VE::sub_even);
263*753f127fSDimitry Andric   Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
264*753f127fSDimitry Andric   // VE loads HiReg from 8(addr) and LoReg from 0(addr)
265*753f127fSDimitry Andric   MachineInstr *StMI =
266*753f127fSDimitry Andric       build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);
267*753f127fSDimitry Andric   replaceFI(*StMI, FrameReg, Offset, 1);
268*753f127fSDimitry Andric   MI.setDesc(get(VE::LDrii));
269*753f127fSDimitry Andric   MI.getOperand(0).setReg(DestHiReg);
270*753f127fSDimitry Andric   Offset += 8;
271*753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
272*753f127fSDimitry Andric }
273*753f127fSDimitry Andric 
274*753f127fSDimitry Andric void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,
275*753f127fSDimitry Andric                                     int64_t Offset, int FIOperandNum) {
276*753f127fSDimitry Andric   switch (MI.getOpcode()) {
277*753f127fSDimitry Andric   case VE::STQrii:
278*753f127fSDimitry Andric     processSTQ(MI, FrameReg, Offset, FIOperandNum);
279*753f127fSDimitry Andric     return;
280*753f127fSDimitry Andric   case VE::LDQrii:
281*753f127fSDimitry Andric     processLDQ(MI, FrameReg, Offset, FIOperandNum);
282*753f127fSDimitry Andric     return;
283*753f127fSDimitry Andric   }
284*753f127fSDimitry Andric   prepareReplaceFI(MI, FrameReg, Offset);
285*753f127fSDimitry Andric   replaceFI(MI, FrameReg, Offset, FIOperandNum);
286*753f127fSDimitry Andric }
287*753f127fSDimitry Andric 
288480093f4SDimitry Andric void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
289480093f4SDimitry Andric                                          int SPAdj, unsigned FIOperandNum,
290480093f4SDimitry Andric                                          RegScavenger *RS) const {
291480093f4SDimitry Andric   assert(SPAdj == 0 && "Unexpected");
292480093f4SDimitry Andric 
293480093f4SDimitry Andric   MachineInstr &MI = *II;
294480093f4SDimitry Andric   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
295*753f127fSDimitry Andric 
296480093f4SDimitry Andric   MachineFunction &MF = *MI.getParent()->getParent();
297*753f127fSDimitry Andric   const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
298*753f127fSDimitry Andric   const VEFrameLowering &TFI = *getFrameLowering(MF);
299*753f127fSDimitry Andric   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
300*753f127fSDimitry Andric   const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();
301*753f127fSDimitry Andric   DebugLoc DL = MI.getDebugLoc();
302*753f127fSDimitry Andric   EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);
303480093f4SDimitry Andric 
304*753f127fSDimitry Andric   // Retrieve FrameReg and byte offset for stack slot.
3055ffd83dbSDimitry Andric   Register FrameReg;
306*753f127fSDimitry Andric   int64_t Offset =
307*753f127fSDimitry Andric       TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
308e8d8bef9SDimitry Andric   Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
309e8d8bef9SDimitry Andric 
310*753f127fSDimitry Andric   EFI.processMI(MI, FrameReg, Offset, FIOperandNum);
311480093f4SDimitry Andric }
312480093f4SDimitry Andric 
313480093f4SDimitry Andric Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
314480093f4SDimitry Andric   return VE::SX9;
315480093f4SDimitry Andric }
316