1 //===-- SparcRegisterInfo.cpp - SPARC Register Information ----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains the SPARC implementation of the TargetRegisterInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "SparcRegisterInfo.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"
27 #define GET_REGINFO_TARGET_DESC
28 #include "SparcGenRegisterInfo.inc"
31 ReserveAppRegisters("sparc-reserve-app-registers", cl::Hidden
, cl::init(false),
32 cl::desc("Reserve application registers (%g2-%g4)"));
34 SparcRegisterInfo::SparcRegisterInfo() : SparcGenRegisterInfo(SP::O7
) {}
37 SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
) const {
42 SparcRegisterInfo::getCallPreservedMask(const MachineFunction
&MF
,
43 CallingConv::ID CC
) const {
48 SparcRegisterInfo::getRTCallPreservedMask(CallingConv::ID CC
) const {
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.
58 // G1-G4 can be used in applications.
59 if (ReserveAppRegisters
) {
64 // G5 is not reserved in 64 bit mode.
65 if (!Subtarget
.is64Bit())
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
);
83 Reserved
.set(SP::O6_O7
);
84 Reserved
.set(SP::I6_I7
);
85 Reserved
.set(SP::G6_G7
);
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
)
96 for (unsigned n
= 0; n
< 31; n
++)
97 Reserved
.set(SP::ASR1
+ n
);
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
);
105 assert(checkAllSuperRegsMarked(Reserved
));
109 bool SparcRegisterInfo::isReservedReg(const MachineFunction
&MF
,
110 MCRegister Reg
) const {
111 return getReservedRegs(MF
)[Reg
];
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
;
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
128 MI
.getOperand(FIOperandNum
).ChangeToRegister(FramePtr
, false);
129 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(Offset
);
133 const TargetInstrInfo
&TII
= *MF
.getSubtarget().getInstrInfo();
135 // FIXME: it would be better to scavenge a register here instead of
136 // reserving G1 all of the time.
138 // Emit nonnegaive immediates with sethi + or.
139 // sethi %hi(Offset), %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
));
147 BuildMI(*MI
.getParent(), II
, dl
, TII
.get(SP::ADDrr
), SP::G1
).addReg(SP::G1
)
149 // Insert: G1+%lo(offset) into the user.
150 MI
.getOperand(FIOperandNum
).ChangeToRegister(SP::G1
, false);
151 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(LO10(Offset
));
155 // Emit Negative numbers with sethi + xor
156 // sethi %hix(Offset), %g1
157 // xor %g1, %lox(offset), %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
));
165 BuildMI(*MI
.getParent(), II
, dl
, TII
.get(SP::ADDrr
), SP::G1
).addReg(SP::G1
)
167 // Insert: G1+%lo(offset) into the user.
168 MI
.getOperand(FIOperandNum
).ChangeToRegister(SP::G1
, false);
169 MI
.getOperand(FIOperandNum
+ 1).ChangeToImmediate(0);
174 SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
175 int SPAdj
, unsigned FIOperandNum
,
176 RegScavenger
*RS
) const {
177 assert(SPAdj
== 0 && "Unexpected");
179 MachineInstr
&MI
= *II
;
180 DebugLoc dl
= MI
.getDebugLoc();
181 int FrameIndex
= MI
.getOperand(FIOperandNum
).getIndex();
182 MachineFunction
&MF
= *MI
.getParent()->getParent();
183 const SparcSubtarget
&Subtarget
= MF
.getSubtarget
<SparcSubtarget
>();
184 const SparcFrameLowering
*TFI
= getFrameLowering(MF
);
188 Offset
= TFI
->getFrameIndexReference(MF
, FrameIndex
, FrameReg
).getFixed();
190 Offset
+= MI
.getOperand(FIOperandNum
+ 1).getImm();
192 if (!Subtarget
.isV9() || !Subtarget
.hasHardQuad()) {
193 if (MI
.getOpcode() == SP::STQFri
) {
194 const TargetInstrInfo
&TII
= *Subtarget
.getInstrInfo();
195 Register SrcReg
= MI
.getOperand(2).getReg();
196 Register SrcEvenReg
= getSubReg(SrcReg
, SP::sub_even64
);
197 Register SrcOddReg
= getSubReg(SrcReg
, SP::sub_odd64
);
199 BuildMI(*MI
.getParent(), II
, dl
, TII
.get(SP::STDFri
))
200 .addReg(FrameReg
).addImm(0).addReg(SrcEvenReg
);
201 replaceFI(MF
, *StMI
, *StMI
, dl
, 0, Offset
, FrameReg
);
202 MI
.setDesc(TII
.get(SP::STDFri
));
203 MI
.getOperand(2).setReg(SrcOddReg
);
205 } else if (MI
.getOpcode() == SP::LDQFri
) {
206 const TargetInstrInfo
&TII
= *Subtarget
.getInstrInfo();
207 Register DestReg
= MI
.getOperand(0).getReg();
208 Register DestEvenReg
= getSubReg(DestReg
, SP::sub_even64
);
209 Register DestOddReg
= getSubReg(DestReg
, SP::sub_odd64
);
211 BuildMI(*MI
.getParent(), II
, dl
, TII
.get(SP::LDDFri
), DestEvenReg
)
212 .addReg(FrameReg
).addImm(0);
213 replaceFI(MF
, *LdMI
, *LdMI
, dl
, 1, Offset
, FrameReg
);
215 MI
.setDesc(TII
.get(SP::LDDFri
));
216 MI
.getOperand(0).setReg(DestOddReg
);
221 replaceFI(MF
, II
, MI
, dl
, FIOperandNum
, Offset
, FrameReg
);
222 // replaceFI never removes II
226 Register
SparcRegisterInfo::getFrameRegister(const MachineFunction
&MF
) const {