Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp
96353 views
1
//===-- CSKYRegisterInfo.h - CSKY Register Information Impl ---*- C++ -*---===//
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 CSKY implementation of the TargetRegisterInfo class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "CSKYRegisterInfo.h"
14
#include "CSKY.h"
15
#include "CSKYSubtarget.h"
16
#include "llvm/CodeGen/MachineFrameInfo.h"
17
#include "llvm/CodeGen/MachineFunction.h"
18
#include "llvm/CodeGen/RegisterScavenging.h"
19
#include "llvm/MC/MCContext.h"
20
21
#define GET_REGINFO_TARGET_DESC
22
#include "CSKYGenRegisterInfo.inc"
23
24
using namespace llvm;
25
26
CSKYRegisterInfo::CSKYRegisterInfo()
27
: CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {}
28
29
const uint32_t *
30
CSKYRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
31
CallingConv::ID Id) const {
32
const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
33
if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat())
34
return CSR_GPR_FPR64_RegMask;
35
if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat())
36
return CSR_GPR_FPR32_RegMask;
37
return CSR_I32_RegMask;
38
}
39
40
Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
41
const TargetFrameLowering *TFI = getFrameLowering(MF);
42
return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14;
43
}
44
45
BitVector CSKYRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
46
const CSKYFrameLowering *TFI = getFrameLowering(MF);
47
const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
48
BitVector Reserved(getNumRegs());
49
50
// Reserve the base register if we need to allocate
51
// variable-sized objects at runtime.
52
if (TFI->hasBP(MF))
53
markSuperRegs(Reserved, CSKY::R7); // bp
54
55
if (TFI->hasFP(MF))
56
markSuperRegs(Reserved, CSKY::R8); // fp
57
58
if (!STI.hasE2()) {
59
for (unsigned i = 0; i < 6; i++)
60
markSuperRegs(Reserved, CSKY::R8 + i); // R8 - R13
61
}
62
63
markSuperRegs(Reserved, CSKY::R14); // sp
64
markSuperRegs(Reserved, CSKY::R15); // lr
65
66
if (!STI.hasHighRegisters()) {
67
for (unsigned i = 0; i < 10; i++)
68
markSuperRegs(Reserved, CSKY::R16 + i); // R16 - R25
69
}
70
71
markSuperRegs(Reserved, CSKY::R26);
72
markSuperRegs(Reserved, CSKY::R27);
73
markSuperRegs(Reserved, CSKY::R28); // gp
74
markSuperRegs(Reserved, CSKY::R29);
75
markSuperRegs(Reserved, CSKY::R30);
76
markSuperRegs(Reserved, CSKY::R31); // tp
77
78
assert(checkAllSuperRegsMarked(Reserved));
79
return Reserved;
80
}
81
82
const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const {
83
return CSR_NoRegs_RegMask;
84
}
85
86
const MCPhysReg *
87
CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
88
const CSKYSubtarget &STI = MF->getSubtarget<CSKYSubtarget>();
89
if (MF->getFunction().hasFnAttribute("interrupt")) {
90
if (STI.hasFPUv3DoubleFloat())
91
return CSR_GPR_FPR64v3_ISR_SaveList;
92
if (STI.hasFPUv3SingleFloat())
93
return CSR_GPR_FPR32v3_ISR_SaveList;
94
if (STI.hasFPUv2DoubleFloat())
95
return CSR_GPR_FPR64_ISR_SaveList;
96
if (STI.hasFPUv2SingleFloat())
97
return CSR_GPR_FPR32_ISR_SaveList;
98
return CSR_GPR_ISR_SaveList;
99
}
100
101
if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat())
102
return CSR_GPR_FPR64_SaveList;
103
if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat())
104
return CSR_GPR_FPR32_SaveList;
105
return CSR_I32_SaveList;
106
}
107
108
static bool IsLegalOffset(const CSKYInstrInfo *TII, MachineInstr *MI,
109
int &Offset) {
110
const MCInstrDesc &Desc = MI->getDesc();
111
unsigned AddrMode = (Desc.TSFlags & CSKYII::AddrModeMask);
112
unsigned i = 0;
113
for (; !MI->getOperand(i).isFI(); ++i) {
114
assert(i + 1 < MI->getNumOperands() &&
115
"Instr doesn't have FrameIndex operand!");
116
}
117
118
if (MI->getOpcode() == CSKY::ADDI32) {
119
if (!isUInt<12>(std::abs(Offset) - 1))
120
return false;
121
if (Offset < 0) {
122
MI->setDesc(TII->get(CSKY::SUBI32));
123
Offset = -Offset;
124
}
125
126
return true;
127
}
128
129
if (MI->getOpcode() == CSKY::ADDI16XZ)
130
return false;
131
132
if (Offset < 0)
133
return false;
134
135
unsigned NumBits = 0;
136
unsigned Scale = 1;
137
switch (AddrMode) {
138
case CSKYII::AddrMode32B:
139
Scale = 1;
140
NumBits = 12;
141
break;
142
case CSKYII::AddrMode32H:
143
Scale = 2;
144
NumBits = 12;
145
break;
146
case CSKYII::AddrMode32WD:
147
Scale = 4;
148
NumBits = 12;
149
break;
150
case CSKYII::AddrMode16B:
151
Scale = 1;
152
NumBits = 5;
153
break;
154
case CSKYII::AddrMode16H:
155
Scale = 2;
156
NumBits = 5;
157
break;
158
case CSKYII::AddrMode16W:
159
Scale = 4;
160
NumBits = 5;
161
break;
162
case CSKYII::AddrMode32SDF:
163
Scale = 4;
164
NumBits = 8;
165
break;
166
default:
167
llvm_unreachable("Unsupported addressing mode!");
168
}
169
170
// Cannot encode offset.
171
if ((Offset & (Scale - 1)) != 0)
172
return false;
173
174
unsigned Mask = (1 << NumBits) - 1;
175
if ((unsigned)Offset <= Mask * Scale)
176
return true;
177
178
// Offset out of range.
179
return false;
180
}
181
182
bool CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
183
int SPAdj, unsigned FIOperandNum,
184
RegScavenger *RS) const {
185
assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
186
187
MachineInstr *MI = &*II;
188
MachineBasicBlock &MBB = *MI->getParent();
189
MachineFunction &MF = *MI->getParent()->getParent();
190
MachineRegisterInfo &MRI = MF.getRegInfo();
191
const CSKYInstrInfo *TII = MF.getSubtarget<CSKYSubtarget>().getInstrInfo();
192
DebugLoc DL = MI->getDebugLoc();
193
const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
194
195
switch (MI->getOpcode()) {
196
default:
197
break;
198
case CSKY::RESTORE_CARRY: {
199
Register NewReg = STI.hasE2()
200
? MRI.createVirtualRegister(&CSKY::GPRRegClass)
201
: MRI.createVirtualRegister(&CSKY::mGPRRegClass);
202
203
auto *Temp = BuildMI(MBB, II, DL, TII->get(CSKY::LD32W), NewReg)
204
.add(MI->getOperand(1))
205
.add(MI->getOperand(2))
206
.getInstr();
207
208
BuildMI(MBB, II, DL, TII->get(STI.hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16),
209
MI->getOperand(0).getReg())
210
.addReg(NewReg, getKillRegState(true))
211
.addImm(0);
212
213
MI = Temp;
214
215
MBB.erase(II);
216
break;
217
}
218
case CSKY::SPILL_CARRY: {
219
Register NewReg;
220
if (STI.hasE2()) {
221
NewReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
222
BuildMI(MBB, II, DL, TII->get(CSKY::MVC32), NewReg)
223
.add(MI->getOperand(0));
224
} else {
225
NewReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
226
BuildMI(MBB, II, DL, TII->get(CSKY::MOVI16), NewReg).addImm(0);
227
BuildMI(MBB, II, DL, TII->get(CSKY::ADDC16))
228
.addReg(NewReg, RegState::Define)
229
.addReg(MI->getOperand(0).getReg(), RegState::Define)
230
.addReg(NewReg, getKillRegState(true))
231
.addReg(NewReg, getKillRegState(true))
232
.addReg(MI->getOperand(0).getReg());
233
234
BuildMI(MBB, II, DL, TII->get(CSKY::BTSTI16), MI->getOperand(0).getReg())
235
.addReg(NewReg)
236
.addImm(0);
237
}
238
239
MI = BuildMI(MBB, II, DL, TII->get(CSKY::ST32W))
240
.addReg(NewReg, getKillRegState(true))
241
.add(MI->getOperand(1))
242
.add(MI->getOperand(2))
243
.getInstr();
244
245
MBB.erase(II);
246
247
break;
248
}
249
}
250
251
int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
252
Register FrameReg;
253
int Offset = getFrameLowering(MF)
254
->getFrameIndexReference(MF, FrameIndex, FrameReg)
255
.getFixed() +
256
MI->getOperand(FIOperandNum + 1).getImm();
257
258
if (!isInt<32>(Offset))
259
report_fatal_error(
260
"Frame offsets outside of the signed 32-bit range not supported");
261
262
bool FrameRegIsKill = false;
263
MachineBasicBlock::iterator NewII(MI);
264
if (!IsLegalOffset(TII, MI, Offset)) {
265
assert(isInt<32>(Offset) && "Int32 expected");
266
// The offset won't fit in an immediate, so use a scratch register instead
267
// Modify Offset and FrameReg appropriately
268
Register ScratchReg = TII->movImm(MBB, NewII, DL, Offset);
269
BuildMI(MBB, NewII, DL,
270
TII->get(STI.hasE2() ? CSKY::ADDU32 : CSKY::ADDU16XZ), ScratchReg)
271
.addReg(ScratchReg, RegState::Kill)
272
.addReg(FrameReg);
273
274
Offset = 0;
275
FrameReg = ScratchReg;
276
FrameRegIsKill = true;
277
}
278
279
if (Offset == 0 &&
280
(MI->getOpcode() == CSKY::ADDI32 || MI->getOpcode() == CSKY::ADDI16XZ)) {
281
MI->setDesc(TII->get(TargetOpcode::COPY));
282
MI->getOperand(FIOperandNum)
283
.ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
284
MI->removeOperand(FIOperandNum + 1);
285
} else {
286
MI->getOperand(FIOperandNum)
287
.ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
288
MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
289
}
290
return false;
291
}
292
293