1 //===-- VERegisterInfo.cpp - VE 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 VE implementation of the TargetRegisterInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "VERegisterInfo.h"
15 #include "VESubtarget.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/Debug.h"
26 #define DEBUG_TYPE "ve-register-info"
28 #define GET_REGINFO_TARGET_DESC
29 #include "VEGenRegisterInfo.inc"
31 // VE uses %s10 == %lp to keep return address
32 VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10
) {}
35 VERegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF
) const {
36 switch (MF
->getFunction().getCallingConv()) {
37 case CallingConv::Fast
:
38 // Being explicit (same as standard CC).
41 case CallingConv::PreserveAll
:
42 return CSR_preserve_all_SaveList
;
46 const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction
&MF
,
47 CallingConv::ID CC
) const {
49 case CallingConv::Fast
:
50 // Being explicit (same as standard CC).
53 case CallingConv::PreserveAll
:
54 return CSR_preserve_all_RegMask
;
58 const uint32_t *VERegisterInfo::getNoPreservedMask() const {
59 return CSR_NoRegs_RegMask
;
62 BitVector
VERegisterInfo::getReservedRegs(const MachineFunction
&MF
) const {
63 BitVector
Reserved(getNumRegs());
65 const Register ReservedRegs
[] = {
66 VE::SX8
, // Stack limit
67 VE::SX9
, // Frame pointer
68 VE::SX10
, // Link register (return address)
69 VE::SX11
, // Stack pointer
71 // FIXME: maybe not need to be reserved
72 VE::SX12
, // Outer register
73 VE::SX13
, // Id register for dynamic linker
75 VE::SX14
, // Thread pointer
76 VE::SX15
, // Global offset table register
77 VE::SX16
, // Procedure linkage table register
78 VE::SX17
, // Linkage-area register
79 // sx18-sx33 are callee-saved registers
80 // sx34-sx63 are temporary registers
83 for (auto R
: ReservedRegs
)
84 for (MCRegAliasIterator
ItAlias(R
, this, true); ItAlias
.isValid();
86 Reserved
.set(*ItAlias
);
88 // Reserve constant registers.
89 Reserved
.set(VE::VM0
);
90 Reserved
.set(VE::VMP0
);
95 const TargetRegisterClass
*
96 VERegisterInfo::getPointerRegClass(const MachineFunction
&MF
,
97 unsigned Kind
) const {
98 return &VE::I64RegClass
;
101 static unsigned offsetToDisp(MachineInstr
&MI
) {
102 // Default offset in instruction's operands (reg+reg+imm).
103 unsigned OffDisp
= 2;
105 #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
108 using namespace llvm::VE
;
109 switch (MI
.getOpcode()) {
111 case RRCAS_multi_cases(TS1AML
):
112 case RRCAS_multi_cases(TS1AMW
):
113 case RRCAS_multi_cases(CASL
):
114 case RRCAS_multi_cases(CASW
):
115 // These instructions use AS format (reg+imm).
120 #undef RRCAS_multi_cases
126 class EliminateFrameIndex
{
127 const TargetInstrInfo
&TII
;
128 const TargetRegisterInfo
&TRI
;
130 MachineBasicBlock
&MBB
;
131 MachineBasicBlock::iterator II
;
134 // Some helper functions for the ease of instruction building.
135 MachineFunction
&getFunc() const { return *MBB
.getParent(); }
136 inline MCRegister
getSubReg(MCRegister Reg
, unsigned Idx
) const {
137 return TRI
.getSubReg(Reg
, Idx
);
139 inline const MCInstrDesc
&get(unsigned Opcode
) const {
140 return TII
.get(Opcode
);
142 inline MachineInstrBuilder
build(const MCInstrDesc
&MCID
, Register DestReg
) {
143 return BuildMI(MBB
, II
, DL
, MCID
, DestReg
);
145 inline MachineInstrBuilder
build(unsigned InstOpc
, Register DestReg
) {
146 return build(get(InstOpc
), DestReg
);
148 inline MachineInstrBuilder
build(const MCInstrDesc
&MCID
) {
149 return BuildMI(MBB
, II
, DL
, MCID
);
151 inline MachineInstrBuilder
build(unsigned InstOpc
) {
152 return build(get(InstOpc
));
155 // Calculate an address of frame index from a frame register and a given
156 // offset if the offset doesn't fit in the immediate field. Use a clobber
157 // register to hold calculated address.
158 void prepareReplaceFI(MachineInstr
&MI
, Register
&FrameReg
, int64_t &Offset
,
160 // Replace the frame index in \p MI with a frame register and a given offset
161 // if it fits in the immediate field. Otherwise, use pre-calculated address
162 // in a clobber regsiter.
163 void replaceFI(MachineInstr
&MI
, Register FrameReg
, int64_t Offset
,
166 // Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
167 void processSTQ(MachineInstr
&MI
, Register FrameReg
, int64_t Offset
,
169 void processLDQ(MachineInstr
&MI
, Register FrameReg
, int64_t Offset
,
171 // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.
172 void processSTVM(MachineInstr
&MI
, Register FrameReg
, int64_t Offset
,
174 void processLDVM(MachineInstr
&MI
, Register FrameReg
, int64_t Offset
,
176 // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.
177 void processSTVM512(MachineInstr
&MI
, Register FrameReg
, int64_t Offset
,
179 void processLDVM512(MachineInstr
&MI
, Register FrameReg
, int64_t Offset
,
183 EliminateFrameIndex(const TargetInstrInfo
&TII
, const TargetRegisterInfo
&TRI
,
184 const DebugLoc
&DL
, MachineBasicBlock
&MBB
,
185 MachineBasicBlock::iterator II
)
186 : TII(TII
), TRI(TRI
), DL(DL
), MBB(MBB
), II(II
), clobber(VE::SX13
) {}
188 // Expand and eliminate Frame Index from MI
189 void processMI(MachineInstr
&MI
, Register FrameReg
, int64_t Offset
,
194 // Prepare the frame index if it doesn't fit in the immediate field. Use
195 // clobber register to hold calculated address.
196 void EliminateFrameIndex::prepareReplaceFI(MachineInstr
&MI
, Register
&FrameReg
,
197 int64_t &Offset
, int64_t Bytes
) {
198 if (isInt
<32>(Offset
) && isInt
<32>(Offset
+ Bytes
)) {
199 // If the offset is small enough to fit in the immediate field, directly
200 // encode it. So, nothing to prepare here.
204 // If the offset doesn't fit, emit following codes. This clobbers SX13
205 // which we always know is available here.
206 // lea %clobber, Offset@lo
207 // and %clobber, %clobber, (32)0
208 // lea.sl %clobber, Offset@hi(FrameReg, %clobber)
209 build(VE::LEAzii
, clobber
).addImm(0).addImm(0).addImm(Lo_32(Offset
));
210 build(VE::ANDrm
, clobber
).addReg(clobber
).addImm(M0(32));
211 build(VE::LEASLrri
, clobber
)
214 .addImm(Hi_32(Offset
));
216 // Use clobber register as a frame register and 0 offset
221 // Replace the frame index in \p MI with a proper byte and framereg offset.
222 void EliminateFrameIndex::replaceFI(MachineInstr
&MI
, Register FrameReg
,
223 int64_t Offset
, int FIOperandNum
) {
224 assert(isInt
<32>(Offset
));
226 // The offset must be small enough to fit in the immediate field after
227 // call of prepareReplaceFI. Therefore, we directly encode it.
228 MI
.getOperand(FIOperandNum
).ChangeToRegister(FrameReg
, false);
229 MI
.getOperand(FIOperandNum
+ offsetToDisp(MI
)).ChangeToImmediate(Offset
);
232 void EliminateFrameIndex::processSTQ(MachineInstr
&MI
, Register FrameReg
,
233 int64_t Offset
, int FIOperandNum
) {
234 assert(MI
.getOpcode() == VE::STQrii
);
235 LLVM_DEBUG(dbgs() << "processSTQ: "; MI
.dump());
237 prepareReplaceFI(MI
, FrameReg
, Offset
, 8);
239 Register SrcReg
= MI
.getOperand(3).getReg();
240 Register SrcHiReg
= getSubReg(SrcReg
, VE::sub_even
);
241 Register SrcLoReg
= getSubReg(SrcReg
, VE::sub_odd
);
242 // VE stores HiReg to 8(addr) and LoReg to 0(addr)
244 build(VE::STrii
).addReg(FrameReg
).addImm(0).addImm(0).addReg(SrcLoReg
);
245 replaceFI(*StMI
, FrameReg
, Offset
, 0);
246 // Mutate to 'hi' store.
247 MI
.setDesc(get(VE::STrii
));
248 MI
.getOperand(3).setReg(SrcHiReg
);
250 replaceFI(MI
, FrameReg
, Offset
, FIOperandNum
);
253 void EliminateFrameIndex::processLDQ(MachineInstr
&MI
, Register FrameReg
,
254 int64_t Offset
, int FIOperandNum
) {
255 assert(MI
.getOpcode() == VE::LDQrii
);
256 LLVM_DEBUG(dbgs() << "processLDQ: "; MI
.dump());
258 prepareReplaceFI(MI
, FrameReg
, Offset
, 8);
260 Register DestReg
= MI
.getOperand(0).getReg();
261 Register DestHiReg
= getSubReg(DestReg
, VE::sub_even
);
262 Register DestLoReg
= getSubReg(DestReg
, VE::sub_odd
);
263 // VE loads HiReg from 8(addr) and LoReg from 0(addr)
265 build(VE::LDrii
, DestLoReg
).addReg(FrameReg
).addImm(0).addImm(0);
266 replaceFI(*StMI
, FrameReg
, Offset
, 1);
267 MI
.setDesc(get(VE::LDrii
));
268 MI
.getOperand(0).setReg(DestHiReg
);
270 replaceFI(MI
, FrameReg
, Offset
, FIOperandNum
);
273 void EliminateFrameIndex::processSTVM(MachineInstr
&MI
, Register FrameReg
,
274 int64_t Offset
, int FIOperandNum
) {
275 assert(MI
.getOpcode() == VE::STVMrii
);
276 LLVM_DEBUG(dbgs() << "processSTVM: "; MI
.dump());
279 // STVMrii frame-index, 0, offset, reg (, memory operand)
281 // SVMi tmp-reg, reg, 0
282 // STrii frame-reg, 0, offset, tmp-reg
283 // SVMi tmp-reg, reg, 1
284 // STrii frame-reg, 0, offset+8, tmp-reg
285 // SVMi tmp-reg, reg, 2
286 // STrii frame-reg, 0, offset+16, tmp-reg
287 // SVMi tmp-reg, reg, 3
288 // STrii frame-reg, 0, offset+24, tmp-reg
290 prepareReplaceFI(MI
, FrameReg
, Offset
, 24);
292 Register SrcReg
= MI
.getOperand(3).getReg();
293 bool isKill
= MI
.getOperand(3).isKill();
294 // FIXME: it would be better to scavenge a register here instead of
295 // reserving SX16 all of the time.
296 Register TmpReg
= VE::SX16
;
297 for (int i
= 0; i
< 3; ++i
) {
298 build(VE::SVMmr
, TmpReg
).addReg(SrcReg
).addImm(i
);
300 build(VE::STrii
).addReg(FrameReg
).addImm(0).addImm(0).addReg(
301 TmpReg
, getKillRegState(true));
302 replaceFI(*StMI
, FrameReg
, Offset
, 0);
305 build(VE::SVMmr
, TmpReg
).addReg(SrcReg
, getKillRegState(isKill
)).addImm(3);
306 MI
.setDesc(get(VE::STrii
));
307 MI
.getOperand(3).ChangeToRegister(TmpReg
, false, false, true);
308 replaceFI(MI
, FrameReg
, Offset
, FIOperandNum
);
311 void EliminateFrameIndex::processLDVM(MachineInstr
&MI
, Register FrameReg
,
312 int64_t Offset
, int FIOperandNum
) {
313 assert(MI
.getOpcode() == VE::LDVMrii
);
314 LLVM_DEBUG(dbgs() << "processLDVM: "; MI
.dump());
317 // LDVMri reg, frame-index, 0, offset (, memory operand)
319 // LDrii tmp-reg, frame-reg, 0, offset
320 // LVMir vm, 0, tmp-reg
321 // LDrii tmp-reg, frame-reg, 0, offset+8
322 // LVMir_m vm, 1, tmp-reg, vm
323 // LDrii tmp-reg, frame-reg, 0, offset+16
324 // LVMir_m vm, 2, tmp-reg, vm
325 // LDrii tmp-reg, frame-reg, 0, offset+24
326 // LVMir_m vm, 3, tmp-reg, vm
328 prepareReplaceFI(MI
, FrameReg
, Offset
, 24);
330 Register DestReg
= MI
.getOperand(0).getReg();
331 // FIXME: it would be better to scavenge a register here instead of
332 // reserving SX16 all of the time.
333 unsigned TmpReg
= VE::SX16
;
334 for (int i
= 0; i
< 4; ++i
) {
337 build(VE::LDrii
, TmpReg
).addReg(FrameReg
).addImm(0).addImm(0);
338 replaceFI(*StMI
, FrameReg
, Offset
, 1);
341 // Last LDrii replace the target instruction.
342 MI
.setDesc(get(VE::LDrii
));
343 MI
.getOperand(0).ChangeToRegister(TmpReg
, true);
345 // First LVM is LVMir. Others are LVMir_m. Last LVM places at the
346 // next of the target instruction.
348 build(VE::LVMir
, DestReg
).addImm(i
).addReg(TmpReg
, getKillRegState(true));
350 build(VE::LVMir_m
, DestReg
)
352 .addReg(TmpReg
, getKillRegState(true))
355 BuildMI(*MI
.getParent(), std::next(II
), DL
, get(VE::LVMir_m
), DestReg
)
357 .addReg(TmpReg
, getKillRegState(true))
360 replaceFI(MI
, FrameReg
, Offset
, FIOperandNum
);
363 void EliminateFrameIndex::processSTVM512(MachineInstr
&MI
, Register FrameReg
,
364 int64_t Offset
, int FIOperandNum
) {
365 assert(MI
.getOpcode() == VE::STVM512rii
);
366 LLVM_DEBUG(dbgs() << "processSTVM512: "; MI
.dump());
368 prepareReplaceFI(MI
, FrameReg
, Offset
, 56);
370 Register SrcReg
= MI
.getOperand(3).getReg();
371 Register SrcLoReg
= getSubReg(SrcReg
, VE::sub_vm_odd
);
372 Register SrcHiReg
= getSubReg(SrcReg
, VE::sub_vm_even
);
373 bool isKill
= MI
.getOperand(3).isKill();
374 // FIXME: it would be better to scavenge a register here instead of
375 // reserving SX16 all of the time.
376 Register TmpReg
= VE::SX16
;
377 // store low part of VMP
378 MachineInstr
*LastMI
= nullptr;
379 for (int i
= 0; i
< 4; ++i
) {
380 LastMI
= build(VE::SVMmr
, TmpReg
).addReg(SrcLoReg
).addImm(i
);
382 build(VE::STrii
).addReg(FrameReg
).addImm(0).addImm(0).addReg(
383 TmpReg
, getKillRegState(true));
384 replaceFI(*StMI
, FrameReg
, Offset
, 0);
388 LastMI
->addRegisterKilled(SrcLoReg
, &TRI
, true);
389 // store high part of VMP
390 for (int i
= 0; i
< 3; ++i
) {
391 build(VE::SVMmr
, TmpReg
).addReg(SrcHiReg
).addImm(i
);
393 build(VE::STrii
).addReg(FrameReg
).addImm(0).addImm(0).addReg(
394 TmpReg
, getKillRegState(true));
395 replaceFI(*StMI
, FrameReg
, Offset
, 0);
398 LastMI
= build(VE::SVMmr
, TmpReg
).addReg(SrcHiReg
).addImm(3);
400 LastMI
->addRegisterKilled(SrcHiReg
, &TRI
, true);
401 // Add implicit super-register kills to the particular MI.
402 LastMI
->addRegisterKilled(SrcReg
, &TRI
, true);
404 MI
.setDesc(get(VE::STrii
));
405 MI
.getOperand(3).ChangeToRegister(TmpReg
, false, false, true);
406 replaceFI(MI
, FrameReg
, Offset
, FIOperandNum
);
409 void EliminateFrameIndex::processLDVM512(MachineInstr
&MI
, Register FrameReg
,
410 int64_t Offset
, int FIOperandNum
) {
411 assert(MI
.getOpcode() == VE::LDVM512rii
);
412 LLVM_DEBUG(dbgs() << "processLDVM512: "; MI
.dump());
414 prepareReplaceFI(MI
, FrameReg
, Offset
, 56);
416 Register DestReg
= MI
.getOperand(0).getReg();
417 Register DestLoReg
= getSubReg(DestReg
, VE::sub_vm_odd
);
418 Register DestHiReg
= getSubReg(DestReg
, VE::sub_vm_even
);
419 // FIXME: it would be better to scavenge a register here instead of
420 // reserving SX16 all of the time.
421 Register TmpReg
= VE::SX16
;
422 build(VE::IMPLICIT_DEF
, DestReg
);
423 for (int i
= 0; i
< 4; ++i
) {
425 build(VE::LDrii
, TmpReg
).addReg(FrameReg
).addImm(0).addImm(0);
426 replaceFI(*LdMI
, FrameReg
, Offset
, 1);
427 build(VE::LVMir_m
, DestLoReg
)
429 .addReg(TmpReg
, getKillRegState(true))
433 for (int i
= 0; i
< 3; ++i
) {
435 build(VE::LDrii
, TmpReg
).addReg(FrameReg
).addImm(0).addImm(0);
436 replaceFI(*LdMI
, FrameReg
, Offset
, 1);
437 build(VE::LVMir_m
, DestHiReg
)
439 .addReg(TmpReg
, getKillRegState(true))
443 MI
.setDesc(get(VE::LDrii
));
444 MI
.getOperand(0).ChangeToRegister(TmpReg
, true);
445 BuildMI(*MI
.getParent(), std::next(II
), DL
, get(VE::LVMir_m
), DestHiReg
)
447 .addReg(TmpReg
, getKillRegState(true))
449 replaceFI(MI
, FrameReg
, Offset
, FIOperandNum
);
452 void EliminateFrameIndex::processMI(MachineInstr
&MI
, Register FrameReg
,
453 int64_t Offset
, int FIOperandNum
) {
454 switch (MI
.getOpcode()) {
456 processSTQ(MI
, FrameReg
, Offset
, FIOperandNum
);
459 processLDQ(MI
, FrameReg
, Offset
, FIOperandNum
);
462 processSTVM(MI
, FrameReg
, Offset
, FIOperandNum
);
465 processLDVM(MI
, FrameReg
, Offset
, FIOperandNum
);
468 processSTVM512(MI
, FrameReg
, Offset
, FIOperandNum
);
471 processLDVM512(MI
, FrameReg
, Offset
, FIOperandNum
);
474 prepareReplaceFI(MI
, FrameReg
, Offset
);
475 replaceFI(MI
, FrameReg
, Offset
, FIOperandNum
);
478 bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II
,
479 int SPAdj
, unsigned FIOperandNum
,
480 RegScavenger
*RS
) const {
481 assert(SPAdj
== 0 && "Unexpected");
483 MachineInstr
&MI
= *II
;
484 int FrameIndex
= MI
.getOperand(FIOperandNum
).getIndex();
486 MachineFunction
&MF
= *MI
.getParent()->getParent();
487 const VESubtarget
&Subtarget
= MF
.getSubtarget
<VESubtarget
>();
488 const VEFrameLowering
&TFI
= *getFrameLowering(MF
);
489 const TargetInstrInfo
&TII
= *Subtarget
.getInstrInfo();
490 const VERegisterInfo
&TRI
= *Subtarget
.getRegisterInfo();
491 DebugLoc DL
= MI
.getDebugLoc();
492 EliminateFrameIndex
EFI(TII
, TRI
, DL
, *MI
.getParent(), II
);
494 // Retrieve FrameReg and byte offset for stack slot.
497 TFI
.getFrameIndexReference(MF
, FrameIndex
, FrameReg
).getFixed();
498 Offset
+= MI
.getOperand(FIOperandNum
+ offsetToDisp(MI
)).getImm();
500 EFI
.processMI(MI
, FrameReg
, Offset
, FIOperandNum
);
504 Register
VERegisterInfo::getFrameRegister(const MachineFunction
&MF
) const {