Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/VERegisterInfo.cpp
96353 views
1
//===-- VERegisterInfo.cpp - VE 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 VE implementation of the TargetRegisterInfo class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "VERegisterInfo.h"
14
#include "VE.h"
15
#include "VESubtarget.h"
16
#include "llvm/ADT/BitVector.h"
17
#include "llvm/ADT/STLExtras.h"
18
#include "llvm/CodeGen/MachineFrameInfo.h"
19
#include "llvm/CodeGen/MachineFunction.h"
20
#include "llvm/CodeGen/MachineInstrBuilder.h"
21
#include "llvm/CodeGen/MachineRegisterInfo.h"
22
#include "llvm/CodeGen/TargetInstrInfo.h"
23
#include "llvm/IR/Type.h"
24
#include "llvm/Support/CommandLine.h"
25
#include "llvm/Support/Debug.h"
26
#include "llvm/Support/ErrorHandling.h"
27
28
using namespace llvm;
29
30
#define DEBUG_TYPE "ve-register-info"
31
32
#define GET_REGINFO_TARGET_DESC
33
#include "VEGenRegisterInfo.inc"
34
35
// VE uses %s10 == %lp to keep return address
36
VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}
37
38
const MCPhysReg *
39
VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
40
switch (MF->getFunction().getCallingConv()) {
41
case CallingConv::Fast:
42
// Being explicit (same as standard CC).
43
default:
44
return CSR_SaveList;
45
case CallingConv::PreserveAll:
46
return CSR_preserve_all_SaveList;
47
}
48
}
49
50
const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF,
51
CallingConv::ID CC) const {
52
switch (CC) {
53
case CallingConv::Fast:
54
// Being explicit (same as standard CC).
55
default:
56
return CSR_RegMask;
57
case CallingConv::PreserveAll:
58
return CSR_preserve_all_RegMask;
59
}
60
}
61
62
const uint32_t *VERegisterInfo::getNoPreservedMask() const {
63
return CSR_NoRegs_RegMask;
64
}
65
66
BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {
67
BitVector Reserved(getNumRegs());
68
69
const Register ReservedRegs[] = {
70
VE::SX8, // Stack limit
71
VE::SX9, // Frame pointer
72
VE::SX10, // Link register (return address)
73
VE::SX11, // Stack pointer
74
75
// FIXME: maybe not need to be reserved
76
VE::SX12, // Outer register
77
VE::SX13, // Id register for dynamic linker
78
79
VE::SX14, // Thread pointer
80
VE::SX15, // Global offset table register
81
VE::SX16, // Procedure linkage table register
82
VE::SX17, // Linkage-area register
83
// sx18-sx33 are callee-saved registers
84
// sx34-sx63 are temporary registers
85
};
86
87
for (auto R : ReservedRegs)
88
for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid();
89
++ItAlias)
90
Reserved.set(*ItAlias);
91
92
// Reserve constant registers.
93
Reserved.set(VE::VM0);
94
Reserved.set(VE::VMP0);
95
96
return Reserved;
97
}
98
99
const TargetRegisterClass *
100
VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
101
unsigned Kind) const {
102
return &VE::I64RegClass;
103
}
104
105
static unsigned offsetToDisp(MachineInstr &MI) {
106
// Default offset in instruction's operands (reg+reg+imm).
107
unsigned OffDisp = 2;
108
109
#define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
110
111
{
112
using namespace llvm::VE;
113
switch (MI.getOpcode()) {
114
case INLINEASM:
115
case RRCAS_multi_cases(TS1AML):
116
case RRCAS_multi_cases(TS1AMW):
117
case RRCAS_multi_cases(CASL):
118
case RRCAS_multi_cases(CASW):
119
// These instructions use AS format (reg+imm).
120
OffDisp = 1;
121
break;
122
}
123
}
124
#undef RRCAS_multi_cases
125
126
return OffDisp;
127
}
128
129
namespace {
130
class EliminateFrameIndex {
131
const TargetInstrInfo &TII;
132
const TargetRegisterInfo &TRI;
133
const DebugLoc &DL;
134
MachineBasicBlock &MBB;
135
MachineBasicBlock::iterator II;
136
Register clobber;
137
138
// Some helper functions for the ease of instruction building.
139
MachineFunction &getFunc() const { return *MBB.getParent(); }
140
inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {
141
return TRI.getSubReg(Reg, Idx);
142
}
143
inline const MCInstrDesc &get(unsigned Opcode) const {
144
return TII.get(Opcode);
145
}
146
inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {
147
return BuildMI(MBB, II, DL, MCID, DestReg);
148
}
149
inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {
150
return build(get(InstOpc), DestReg);
151
}
152
inline MachineInstrBuilder build(const MCInstrDesc &MCID) {
153
return BuildMI(MBB, II, DL, MCID);
154
}
155
inline MachineInstrBuilder build(unsigned InstOpc) {
156
return build(get(InstOpc));
157
}
158
159
// Calculate an address of frame index from a frame register and a given
160
// offset if the offset doesn't fit in the immediate field. Use a clobber
161
// register to hold calculated address.
162
void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,
163
int64_t Bytes = 0);
164
// Replace the frame index in \p MI with a frame register and a given offset
165
// if it fits in the immediate field. Otherwise, use pre-calculated address
166
// in a clobber regsiter.
167
void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,
168
int FIOperandNum);
169
170
// Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
171
void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
172
int FIOperandNum);
173
void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
174
int FIOperandNum);
175
// Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.
176
void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
177
int FIOperandNum);
178
void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
179
int FIOperandNum);
180
// Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.
181
void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
182
int FIOperandNum);
183
void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
184
int FIOperandNum);
185
186
public:
187
EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
188
const DebugLoc &DL, MachineBasicBlock &MBB,
189
MachineBasicBlock::iterator II)
190
: TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}
191
192
// Expand and eliminate Frame Index from MI
193
void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,
194
int FIOperandNum);
195
};
196
} // namespace
197
198
// Prepare the frame index if it doesn't fit in the immediate field. Use
199
// clobber register to hold calculated address.
200
void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,
201
int64_t &Offset, int64_t Bytes) {
202
if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {
203
// If the offset is small enough to fit in the immediate field, directly
204
// encode it. So, nothing to prepare here.
205
return;
206
}
207
208
// If the offset doesn't fit, emit following codes. This clobbers SX13
209
// which we always know is available here.
210
// lea %clobber, Offset@lo
211
// and %clobber, %clobber, (32)0
212
// lea.sl %clobber, Offset@hi(FrameReg, %clobber)
213
build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));
214
build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));
215
build(VE::LEASLrri, clobber)
216
.addReg(clobber)
217
.addReg(FrameReg)
218
.addImm(Hi_32(Offset));
219
220
// Use clobber register as a frame register and 0 offset
221
FrameReg = clobber;
222
Offset = 0;
223
}
224
225
// Replace the frame index in \p MI with a proper byte and framereg offset.
226
void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,
227
int64_t Offset, int FIOperandNum) {
228
assert(isInt<32>(Offset));
229
230
// The offset must be small enough to fit in the immediate field after
231
// call of prepareReplaceFI. Therefore, we directly encode it.
232
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
233
MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
234
}
235
236
void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,
237
int64_t Offset, int FIOperandNum) {
238
assert(MI.getOpcode() == VE::STQrii);
239
LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());
240
241
prepareReplaceFI(MI, FrameReg, Offset, 8);
242
243
Register SrcReg = MI.getOperand(3).getReg();
244
Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
245
Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
246
// VE stores HiReg to 8(addr) and LoReg to 0(addr)
247
MachineInstr *StMI =
248
build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);
249
replaceFI(*StMI, FrameReg, Offset, 0);
250
// Mutate to 'hi' store.
251
MI.setDesc(get(VE::STrii));
252
MI.getOperand(3).setReg(SrcHiReg);
253
Offset += 8;
254
replaceFI(MI, FrameReg, Offset, FIOperandNum);
255
}
256
257
void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,
258
int64_t Offset, int FIOperandNum) {
259
assert(MI.getOpcode() == VE::LDQrii);
260
LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());
261
262
prepareReplaceFI(MI, FrameReg, Offset, 8);
263
264
Register DestReg = MI.getOperand(0).getReg();
265
Register DestHiReg = getSubReg(DestReg, VE::sub_even);
266
Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
267
// VE loads HiReg from 8(addr) and LoReg from 0(addr)
268
MachineInstr *StMI =
269
build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);
270
replaceFI(*StMI, FrameReg, Offset, 1);
271
MI.setDesc(get(VE::LDrii));
272
MI.getOperand(0).setReg(DestHiReg);
273
Offset += 8;
274
replaceFI(MI, FrameReg, Offset, FIOperandNum);
275
}
276
277
void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg,
278
int64_t Offset, int FIOperandNum) {
279
assert(MI.getOpcode() == VE::STVMrii);
280
LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump());
281
282
// Original MI is:
283
// STVMrii frame-index, 0, offset, reg (, memory operand)
284
// Convert it to:
285
// SVMi tmp-reg, reg, 0
286
// STrii frame-reg, 0, offset, tmp-reg
287
// SVMi tmp-reg, reg, 1
288
// STrii frame-reg, 0, offset+8, tmp-reg
289
// SVMi tmp-reg, reg, 2
290
// STrii frame-reg, 0, offset+16, tmp-reg
291
// SVMi tmp-reg, reg, 3
292
// STrii frame-reg, 0, offset+24, tmp-reg
293
294
prepareReplaceFI(MI, FrameReg, Offset, 24);
295
296
Register SrcReg = MI.getOperand(3).getReg();
297
bool isKill = MI.getOperand(3).isKill();
298
// FIXME: it would be better to scavenge a register here instead of
299
// reserving SX16 all of the time.
300
Register TmpReg = VE::SX16;
301
for (int i = 0; i < 3; ++i) {
302
build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i);
303
MachineInstr *StMI =
304
build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
305
TmpReg, getKillRegState(true));
306
replaceFI(*StMI, FrameReg, Offset, 0);
307
Offset += 8;
308
}
309
build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3);
310
MI.setDesc(get(VE::STrii));
311
MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
312
replaceFI(MI, FrameReg, Offset, FIOperandNum);
313
}
314
315
void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg,
316
int64_t Offset, int FIOperandNum) {
317
assert(MI.getOpcode() == VE::LDVMrii);
318
LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump());
319
320
// Original MI is:
321
// LDVMri reg, frame-index, 0, offset (, memory operand)
322
// Convert it to:
323
// LDrii tmp-reg, frame-reg, 0, offset
324
// LVMir vm, 0, tmp-reg
325
// LDrii tmp-reg, frame-reg, 0, offset+8
326
// LVMir_m vm, 1, tmp-reg, vm
327
// LDrii tmp-reg, frame-reg, 0, offset+16
328
// LVMir_m vm, 2, tmp-reg, vm
329
// LDrii tmp-reg, frame-reg, 0, offset+24
330
// LVMir_m vm, 3, tmp-reg, vm
331
332
prepareReplaceFI(MI, FrameReg, Offset, 24);
333
334
Register DestReg = MI.getOperand(0).getReg();
335
// FIXME: it would be better to scavenge a register here instead of
336
// reserving SX16 all of the time.
337
unsigned TmpReg = VE::SX16;
338
for (int i = 0; i < 4; ++i) {
339
if (i != 3) {
340
MachineInstr *StMI =
341
build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
342
replaceFI(*StMI, FrameReg, Offset, 1);
343
Offset += 8;
344
} else {
345
// Last LDrii replace the target instruction.
346
MI.setDesc(get(VE::LDrii));
347
MI.getOperand(0).ChangeToRegister(TmpReg, true);
348
}
349
// First LVM is LVMir. Others are LVMir_m. Last LVM places at the
350
// next of the target instruction.
351
if (i == 0)
352
build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true));
353
else if (i != 3)
354
build(VE::LVMir_m, DestReg)
355
.addImm(i)
356
.addReg(TmpReg, getKillRegState(true))
357
.addReg(DestReg);
358
else
359
BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg)
360
.addImm(3)
361
.addReg(TmpReg, getKillRegState(true))
362
.addReg(DestReg);
363
}
364
replaceFI(MI, FrameReg, Offset, FIOperandNum);
365
}
366
367
void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg,
368
int64_t Offset, int FIOperandNum) {
369
assert(MI.getOpcode() == VE::STVM512rii);
370
LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump());
371
372
prepareReplaceFI(MI, FrameReg, Offset, 56);
373
374
Register SrcReg = MI.getOperand(3).getReg();
375
Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd);
376
Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even);
377
bool isKill = MI.getOperand(3).isKill();
378
// FIXME: it would be better to scavenge a register here instead of
379
// reserving SX16 all of the time.
380
Register TmpReg = VE::SX16;
381
// store low part of VMP
382
MachineInstr *LastMI = nullptr;
383
for (int i = 0; i < 4; ++i) {
384
LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i);
385
MachineInstr *StMI =
386
build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
387
TmpReg, getKillRegState(true));
388
replaceFI(*StMI, FrameReg, Offset, 0);
389
Offset += 8;
390
}
391
if (isKill)
392
LastMI->addRegisterKilled(SrcLoReg, &TRI, true);
393
// store high part of VMP
394
for (int i = 0; i < 3; ++i) {
395
build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i);
396
MachineInstr *StMI =
397
build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
398
TmpReg, getKillRegState(true));
399
replaceFI(*StMI, FrameReg, Offset, 0);
400
Offset += 8;
401
}
402
LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3);
403
if (isKill) {
404
LastMI->addRegisterKilled(SrcHiReg, &TRI, true);
405
// Add implicit super-register kills to the particular MI.
406
LastMI->addRegisterKilled(SrcReg, &TRI, true);
407
}
408
MI.setDesc(get(VE::STrii));
409
MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
410
replaceFI(MI, FrameReg, Offset, FIOperandNum);
411
}
412
413
void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg,
414
int64_t Offset, int FIOperandNum) {
415
assert(MI.getOpcode() == VE::LDVM512rii);
416
LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump());
417
418
prepareReplaceFI(MI, FrameReg, Offset, 56);
419
420
Register DestReg = MI.getOperand(0).getReg();
421
Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd);
422
Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even);
423
// FIXME: it would be better to scavenge a register here instead of
424
// reserving SX16 all of the time.
425
Register TmpReg = VE::SX16;
426
build(VE::IMPLICIT_DEF, DestReg);
427
for (int i = 0; i < 4; ++i) {
428
MachineInstr *LdMI =
429
build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
430
replaceFI(*LdMI, FrameReg, Offset, 1);
431
build(VE::LVMir_m, DestLoReg)
432
.addImm(i)
433
.addReg(TmpReg, getKillRegState(true))
434
.addReg(DestLoReg);
435
Offset += 8;
436
}
437
for (int i = 0; i < 3; ++i) {
438
MachineInstr *LdMI =
439
build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
440
replaceFI(*LdMI, FrameReg, Offset, 1);
441
build(VE::LVMir_m, DestHiReg)
442
.addImm(i)
443
.addReg(TmpReg, getKillRegState(true))
444
.addReg(DestHiReg);
445
Offset += 8;
446
}
447
MI.setDesc(get(VE::LDrii));
448
MI.getOperand(0).ChangeToRegister(TmpReg, true);
449
BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg)
450
.addImm(3)
451
.addReg(TmpReg, getKillRegState(true))
452
.addReg(DestHiReg);
453
replaceFI(MI, FrameReg, Offset, FIOperandNum);
454
}
455
456
void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,
457
int64_t Offset, int FIOperandNum) {
458
switch (MI.getOpcode()) {
459
case VE::STQrii:
460
processSTQ(MI, FrameReg, Offset, FIOperandNum);
461
return;
462
case VE::LDQrii:
463
processLDQ(MI, FrameReg, Offset, FIOperandNum);
464
return;
465
case VE::STVMrii:
466
processSTVM(MI, FrameReg, Offset, FIOperandNum);
467
return;
468
case VE::LDVMrii:
469
processLDVM(MI, FrameReg, Offset, FIOperandNum);
470
return;
471
case VE::STVM512rii:
472
processSTVM512(MI, FrameReg, Offset, FIOperandNum);
473
return;
474
case VE::LDVM512rii:
475
processLDVM512(MI, FrameReg, Offset, FIOperandNum);
476
return;
477
}
478
prepareReplaceFI(MI, FrameReg, Offset);
479
replaceFI(MI, FrameReg, Offset, FIOperandNum);
480
}
481
482
bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
483
int SPAdj, unsigned FIOperandNum,
484
RegScavenger *RS) const {
485
assert(SPAdj == 0 && "Unexpected");
486
487
MachineInstr &MI = *II;
488
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
489
490
MachineFunction &MF = *MI.getParent()->getParent();
491
const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
492
const VEFrameLowering &TFI = *getFrameLowering(MF);
493
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
494
const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();
495
DebugLoc DL = MI.getDebugLoc();
496
EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);
497
498
// Retrieve FrameReg and byte offset for stack slot.
499
Register FrameReg;
500
int64_t Offset =
501
TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
502
Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
503
504
EFI.processMI(MI, FrameReg, Offset, FIOperandNum);
505
return false;
506
}
507
508
Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
509
return VE::SX9;
510
}
511
512