SparcRegisterInfo.cpp revision 360784
1//===-- SparcRegisterInfo.cpp - SPARC 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 SPARC implementation of the TargetRegisterInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "SparcRegisterInfo.h"
14#include "Sparc.h"
15#include "SparcMachineFunctionInfo.h"
16#include "SparcSubtarget.h"
17#include "llvm/ADT/BitVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/CodeGen/TargetInstrInfo.h"
23#include "llvm/IR/Type.h"
24#include "llvm/Support/CommandLine.h"
25#include "llvm/Support/ErrorHandling.h"
26
27using namespace llvm;
28
29#define GET_REGINFO_TARGET_DESC
30#include "SparcGenRegisterInfo.inc"
31
32static cl::opt<bool>
33ReserveAppRegisters("sparc-reserve-app-registers", cl::Hidden, cl::init(false),
34                    cl::desc("Reserve application registers (%g2-%g4)"));
35
36SparcRegisterInfo::SparcRegisterInfo() : SparcGenRegisterInfo(SP::O7) {}
37
38const MCPhysReg*
39SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
40  return CSR_SaveList;
41}
42
43const uint32_t *
44SparcRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
45                                        CallingConv::ID CC) const {
46  return CSR_RegMask;
47}
48
49const uint32_t*
50SparcRegisterInfo::getRTCallPreservedMask(CallingConv::ID CC) const {
51  return RTCSR_RegMask;
52}
53
54BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
55  BitVector Reserved(getNumRegs());
56  const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
57  // FIXME: G1 reserved for now for large imm generation by frame code.
58  Reserved.set(SP::G1);
59
60  // G1-G4 can be used in applications.
61  if (ReserveAppRegisters) {
62    Reserved.set(SP::G2);
63    Reserved.set(SP::G3);
64    Reserved.set(SP::G4);
65  }
66  // G5 is not reserved in 64 bit mode.
67  if (!Subtarget.is64Bit())
68    Reserved.set(SP::G5);
69
70  Reserved.set(SP::O6);
71  Reserved.set(SP::I6);
72  Reserved.set(SP::I7);
73  Reserved.set(SP::G0);
74  Reserved.set(SP::G6);
75  Reserved.set(SP::G7);
76
77  // Also reserve the register pair aliases covering the above
78  // registers, with the same conditions.
79  Reserved.set(SP::G0_G1);
80  if (ReserveAppRegisters)
81    Reserved.set(SP::G2_G3);
82  if (ReserveAppRegisters || !Subtarget.is64Bit())
83    Reserved.set(SP::G4_G5);
84
85  Reserved.set(SP::O6_O7);
86  Reserved.set(SP::I6_I7);
87  Reserved.set(SP::G6_G7);
88
89  // Unaliased double registers are not available in non-V9 targets.
90  if (!Subtarget.isV9()) {
91    for (unsigned n = 0; n != 16; ++n) {
92      for (MCRegAliasIterator AI(SP::D16 + n, this, true); AI.isValid(); ++AI)
93        Reserved.set(*AI);
94    }
95  }
96
97  // Reserve ASR1-ASR31
98  for (unsigned n = 0; n < 31; n++)
99    Reserved.set(SP::ASR1 + n);
100
101  return Reserved;
102}
103
104const TargetRegisterClass*
105SparcRegisterInfo::getPointerRegClass(const MachineFunction &MF,
106                                      unsigned Kind) const {
107  const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
108  return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
109}
110
111static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II,
112                      MachineInstr &MI, const DebugLoc &dl,
113                      unsigned FIOperandNum, int Offset, unsigned FramePtr) {
114  // Replace frame index with a frame pointer reference.
115  if (Offset >= -4096 && Offset <= 4095) {
116    // If the offset is small enough to fit in the immediate field, directly
117    // encode it.
118    MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
119    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
120    return;
121  }
122
123  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
124
125  // FIXME: it would be better to scavenge a register here instead of
126  // reserving G1 all of the time.
127  if (Offset >= 0) {
128    // Emit nonnegaive immediates with sethi + or.
129    // sethi %hi(Offset), %g1
130    // add %g1, %fp, %g1
131    // Insert G1+%lo(offset) into the user.
132    BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)
133      .addImm(HI22(Offset));
134
135
136    // Emit G1 = G1 + I6
137    BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
138      .addReg(FramePtr);
139    // Insert: G1+%lo(offset) into the user.
140    MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
141    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset));
142    return;
143  }
144
145  // Emit Negative numbers with sethi + xor
146  // sethi %hix(Offset), %g1
147  // xor  %g1, %lox(offset), %g1
148  // add %g1, %fp, %g1
149  // Insert: G1 + 0 into the user.
150  BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)
151    .addImm(HIX22(Offset));
152  BuildMI(*MI.getParent(), II, dl, TII.get(SP::XORri), SP::G1)
153    .addReg(SP::G1).addImm(LOX10(Offset));
154
155  BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
156    .addReg(FramePtr);
157  // Insert: G1+%lo(offset) into the user.
158  MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
159  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
160}
161
162
163void
164SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
165                                       int SPAdj, unsigned FIOperandNum,
166                                       RegScavenger *RS) const {
167  assert(SPAdj == 0 && "Unexpected");
168
169  MachineInstr &MI = *II;
170  DebugLoc dl = MI.getDebugLoc();
171  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
172  MachineFunction &MF = *MI.getParent()->getParent();
173  const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
174  const SparcFrameLowering *TFI = getFrameLowering(MF);
175
176  unsigned FrameReg;
177  int Offset;
178  Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg);
179
180  Offset += MI.getOperand(FIOperandNum + 1).getImm();
181
182  if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) {
183    if (MI.getOpcode() == SP::STQFri) {
184      const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
185      Register SrcReg = MI.getOperand(2).getReg();
186      Register SrcEvenReg = getSubReg(SrcReg, SP::sub_even64);
187      Register SrcOddReg = getSubReg(SrcReg, SP::sub_odd64);
188      MachineInstr *StMI =
189        BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri))
190        .addReg(FrameReg).addImm(0).addReg(SrcEvenReg);
191      replaceFI(MF, *StMI, *StMI, dl, 0, Offset, FrameReg);
192      MI.setDesc(TII.get(SP::STDFri));
193      MI.getOperand(2).setReg(SrcOddReg);
194      Offset += 8;
195    } else if (MI.getOpcode() == SP::LDQFri) {
196      const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
197      Register DestReg = MI.getOperand(0).getReg();
198      Register DestEvenReg = getSubReg(DestReg, SP::sub_even64);
199      Register DestOddReg = getSubReg(DestReg, SP::sub_odd64);
200      MachineInstr *LdMI =
201        BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg)
202        .addReg(FrameReg).addImm(0);
203      replaceFI(MF, *LdMI, *LdMI, dl, 1, Offset, FrameReg);
204
205      MI.setDesc(TII.get(SP::LDDFri));
206      MI.getOperand(0).setReg(DestOddReg);
207      Offset += 8;
208    }
209  }
210
211  replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg);
212
213}
214
215Register SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
216  return SP::I6;
217}
218
219// Sparc has no architectural need for stack realignment support,
220// except that LLVM unfortunately currently implements overaligned
221// stack objects by depending upon stack realignment support.
222// If that ever changes, this can probably be deleted.
223bool SparcRegisterInfo::canRealignStack(const MachineFunction &MF) const {
224  if (!TargetRegisterInfo::canRealignStack(MF))
225    return false;
226
227  // Sparc always has a fixed frame pointer register, so don't need to
228  // worry about needing to reserve it. [even if we don't have a frame
229  // pointer for our frame, it still cannot be used for other things,
230  // or register window traps will be SADNESS.]
231
232  // If there's a reserved call frame, we can use SP to access locals.
233  if (getFrameLowering(MF)->hasReservedCallFrame(MF))
234    return true;
235
236  // Otherwise, we'd need a base pointer, but those aren't implemented
237  // for SPARC at the moment.
238
239  return false;
240}
241