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