xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===- XtensaRegisterInfo.cpp - Xtensa Register Information ---------------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric // This file contains the Xtensa implementation of the TargetRegisterInfo class.
10*0fca6ea1SDimitry Andric //
11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
12*0fca6ea1SDimitry Andric 
13*0fca6ea1SDimitry Andric #include "XtensaRegisterInfo.h"
14*0fca6ea1SDimitry Andric #include "XtensaInstrInfo.h"
15*0fca6ea1SDimitry Andric #include "XtensaSubtarget.h"
16*0fca6ea1SDimitry Andric #include "XtensaUtils.h"
17*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
18*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
19*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
20*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
21*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h"
22*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
23*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h"
24*0fca6ea1SDimitry Andric 
25*0fca6ea1SDimitry Andric #define DEBUG_TYPE "xtensa-reg-info"
26*0fca6ea1SDimitry Andric 
27*0fca6ea1SDimitry Andric #define GET_REGINFO_TARGET_DESC
28*0fca6ea1SDimitry Andric #include "XtensaGenRegisterInfo.inc"
29*0fca6ea1SDimitry Andric 
30*0fca6ea1SDimitry Andric using namespace llvm;
31*0fca6ea1SDimitry Andric 
XtensaRegisterInfo(const XtensaSubtarget & STI)32*0fca6ea1SDimitry Andric XtensaRegisterInfo::XtensaRegisterInfo(const XtensaSubtarget &STI)
33*0fca6ea1SDimitry Andric     : XtensaGenRegisterInfo(Xtensa::A0), Subtarget(STI) {}
34*0fca6ea1SDimitry Andric 
35*0fca6ea1SDimitry Andric const uint16_t *
getCalleeSavedRegs(const MachineFunction * MF) const36*0fca6ea1SDimitry Andric XtensaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
37*0fca6ea1SDimitry Andric   return CSR_Xtensa_SaveList;
38*0fca6ea1SDimitry Andric }
39*0fca6ea1SDimitry Andric 
40*0fca6ea1SDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID) const41*0fca6ea1SDimitry Andric XtensaRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
42*0fca6ea1SDimitry Andric                                          CallingConv::ID) const {
43*0fca6ea1SDimitry Andric   return CSR_Xtensa_RegMask;
44*0fca6ea1SDimitry Andric }
45*0fca6ea1SDimitry Andric 
getReservedRegs(const MachineFunction & MF) const46*0fca6ea1SDimitry Andric BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
47*0fca6ea1SDimitry Andric   BitVector Reserved(getNumRegs());
48*0fca6ea1SDimitry Andric   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
49*0fca6ea1SDimitry Andric 
50*0fca6ea1SDimitry Andric   Reserved.set(Xtensa::A0);
51*0fca6ea1SDimitry Andric   if (TFI->hasFP(MF)) {
52*0fca6ea1SDimitry Andric     // Reserve frame pointer.
53*0fca6ea1SDimitry Andric     Reserved.set(getFrameRegister(MF));
54*0fca6ea1SDimitry Andric   }
55*0fca6ea1SDimitry Andric 
56*0fca6ea1SDimitry Andric   // Reserve stack pointer.
57*0fca6ea1SDimitry Andric   Reserved.set(Xtensa::SP);
58*0fca6ea1SDimitry Andric   return Reserved;
59*0fca6ea1SDimitry Andric }
60*0fca6ea1SDimitry Andric 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const61*0fca6ea1SDimitry Andric bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
62*0fca6ea1SDimitry Andric                                              int SPAdj, unsigned FIOperandNum,
63*0fca6ea1SDimitry Andric                                              RegScavenger *RS) const {
64*0fca6ea1SDimitry Andric   MachineInstr &MI = *II;
65*0fca6ea1SDimitry Andric   MachineFunction &MF = *MI.getParent()->getParent();
66*0fca6ea1SDimitry Andric   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
67*0fca6ea1SDimitry Andric   uint64_t StackSize = MF.getFrameInfo().getStackSize();
68*0fca6ea1SDimitry Andric   int64_t SPOffset = MF.getFrameInfo().getObjectOffset(FrameIndex);
69*0fca6ea1SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
70*0fca6ea1SDimitry Andric   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
71*0fca6ea1SDimitry Andric   int MinCSFI = 0;
72*0fca6ea1SDimitry Andric   int MaxCSFI = -1;
73*0fca6ea1SDimitry Andric 
74*0fca6ea1SDimitry Andric   if (CSI.size()) {
75*0fca6ea1SDimitry Andric     MinCSFI = CSI[0].getFrameIdx();
76*0fca6ea1SDimitry Andric     MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
77*0fca6ea1SDimitry Andric   }
78*0fca6ea1SDimitry Andric   // The following stack frame objects are always referenced relative to $sp:
79*0fca6ea1SDimitry Andric   //  1. Outgoing arguments.
80*0fca6ea1SDimitry Andric   //  2. Pointer to dynamically allocated stack space.
81*0fca6ea1SDimitry Andric   //  3. Locations for callee-saved registers.
82*0fca6ea1SDimitry Andric   //  4. Locations for eh data registers.
83*0fca6ea1SDimitry Andric   // Everything else is referenced relative to whatever register
84*0fca6ea1SDimitry Andric   // getFrameRegister() returns.
85*0fca6ea1SDimitry Andric   unsigned FrameReg;
86*0fca6ea1SDimitry Andric   if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI))
87*0fca6ea1SDimitry Andric     FrameReg = Xtensa::SP;
88*0fca6ea1SDimitry Andric   else
89*0fca6ea1SDimitry Andric     FrameReg = getFrameRegister(MF);
90*0fca6ea1SDimitry Andric 
91*0fca6ea1SDimitry Andric   // Calculate final offset.
92*0fca6ea1SDimitry Andric   // - There is no need to change the offset if the frame object is one of the
93*0fca6ea1SDimitry Andric   //   following: an outgoing argument, pointer to a dynamically allocated
94*0fca6ea1SDimitry Andric   //   stack space or a $gp restore location,
95*0fca6ea1SDimitry Andric   // - If the frame object is any of the following, its offset must be adjusted
96*0fca6ea1SDimitry Andric   //   by adding the size of the stack:
97*0fca6ea1SDimitry Andric   //   incoming argument, callee-saved register location or local variable.
98*0fca6ea1SDimitry Andric   bool IsKill = false;
99*0fca6ea1SDimitry Andric   int64_t Offset =
100*0fca6ea1SDimitry Andric       SPOffset + (int64_t)StackSize + MI.getOperand(FIOperandNum + 1).getImm();
101*0fca6ea1SDimitry Andric 
102*0fca6ea1SDimitry Andric   bool Valid = isValidAddrOffset(MI, Offset);
103*0fca6ea1SDimitry Andric 
104*0fca6ea1SDimitry Andric   // If MI is not a debug value, make sure Offset fits in the 16-bit immediate
105*0fca6ea1SDimitry Andric   // field.
106*0fca6ea1SDimitry Andric   if (!MI.isDebugValue() && !Valid) {
107*0fca6ea1SDimitry Andric     MachineBasicBlock &MBB = *MI.getParent();
108*0fca6ea1SDimitry Andric     DebugLoc DL = II->getDebugLoc();
109*0fca6ea1SDimitry Andric     unsigned ADD = Xtensa::ADD;
110*0fca6ea1SDimitry Andric     unsigned Reg;
111*0fca6ea1SDimitry Andric     const XtensaInstrInfo &TII = *static_cast<const XtensaInstrInfo *>(
112*0fca6ea1SDimitry Andric         MBB.getParent()->getSubtarget().getInstrInfo());
113*0fca6ea1SDimitry Andric 
114*0fca6ea1SDimitry Andric     TII.loadImmediate(MBB, II, &Reg, Offset);
115*0fca6ea1SDimitry Andric     BuildMI(MBB, II, DL, TII.get(ADD), Reg)
116*0fca6ea1SDimitry Andric         .addReg(FrameReg)
117*0fca6ea1SDimitry Andric         .addReg(Reg, RegState::Kill);
118*0fca6ea1SDimitry Andric 
119*0fca6ea1SDimitry Andric     FrameReg = Reg;
120*0fca6ea1SDimitry Andric     Offset = 0;
121*0fca6ea1SDimitry Andric     IsKill = true;
122*0fca6ea1SDimitry Andric   }
123*0fca6ea1SDimitry Andric 
124*0fca6ea1SDimitry Andric   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, IsKill);
125*0fca6ea1SDimitry Andric   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
126*0fca6ea1SDimitry Andric 
127*0fca6ea1SDimitry Andric   return false;
128*0fca6ea1SDimitry Andric }
129*0fca6ea1SDimitry Andric 
getFrameRegister(const MachineFunction & MF) const130*0fca6ea1SDimitry Andric Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
131*0fca6ea1SDimitry Andric   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
132*0fca6ea1SDimitry Andric   return TFI->hasFP(MF) ? Xtensa::A15 : Xtensa::SP;
133*0fca6ea1SDimitry Andric }
134