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