1349cc55cSDimitry Andric //===-- CSKYRegisterInfo.h - CSKY Register Information Impl ---*- C++ -*---===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric //
9349cc55cSDimitry Andric // This file contains the CSKY implementation of the TargetRegisterInfo class.
10349cc55cSDimitry Andric //
11349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
12349cc55cSDimitry Andric
13349cc55cSDimitry Andric #include "CSKYRegisterInfo.h"
14349cc55cSDimitry Andric #include "CSKY.h"
15349cc55cSDimitry Andric #include "CSKYSubtarget.h"
1681ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
17349cc55cSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
18349cc55cSDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h"
19349cc55cSDimitry Andric #include "llvm/MC/MCContext.h"
20349cc55cSDimitry Andric
21349cc55cSDimitry Andric #define GET_REGINFO_TARGET_DESC
22349cc55cSDimitry Andric #include "CSKYGenRegisterInfo.inc"
23349cc55cSDimitry Andric
24349cc55cSDimitry Andric using namespace llvm;
25349cc55cSDimitry Andric
CSKYRegisterInfo()26349cc55cSDimitry Andric CSKYRegisterInfo::CSKYRegisterInfo()
27349cc55cSDimitry Andric : CSKYGenRegisterInfo(CSKY::R15, 0, 0, 0) {}
28349cc55cSDimitry Andric
29349cc55cSDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID Id) const30349cc55cSDimitry Andric CSKYRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
31349cc55cSDimitry Andric CallingConv::ID Id) const {
32349cc55cSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
3381ad6265SDimitry Andric if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat())
3481ad6265SDimitry Andric return CSR_GPR_FPR64_RegMask;
3581ad6265SDimitry Andric if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat())
3681ad6265SDimitry Andric return CSR_GPR_FPR32_RegMask;
37349cc55cSDimitry Andric return CSR_I32_RegMask;
38349cc55cSDimitry Andric }
39349cc55cSDimitry Andric
getFrameRegister(const MachineFunction & MF) const40349cc55cSDimitry Andric Register CSKYRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
41349cc55cSDimitry Andric const TargetFrameLowering *TFI = getFrameLowering(MF);
42349cc55cSDimitry Andric return TFI->hasFP(MF) ? CSKY::R8 : CSKY::R14;
43349cc55cSDimitry Andric }
44349cc55cSDimitry Andric
getReservedRegs(const MachineFunction & MF) const45349cc55cSDimitry Andric BitVector CSKYRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
46349cc55cSDimitry Andric const CSKYFrameLowering *TFI = getFrameLowering(MF);
47349cc55cSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
48349cc55cSDimitry Andric BitVector Reserved(getNumRegs());
49349cc55cSDimitry Andric
50349cc55cSDimitry Andric // Reserve the base register if we need to allocate
51349cc55cSDimitry Andric // variable-sized objects at runtime.
52349cc55cSDimitry Andric if (TFI->hasBP(MF))
53349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R7); // bp
54349cc55cSDimitry Andric
55349cc55cSDimitry Andric if (TFI->hasFP(MF))
56349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R8); // fp
57349cc55cSDimitry Andric
58349cc55cSDimitry Andric if (!STI.hasE2()) {
59349cc55cSDimitry Andric for (unsigned i = 0; i < 6; i++)
60349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R8 + i); // R8 - R13
61349cc55cSDimitry Andric }
62349cc55cSDimitry Andric
63349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R14); // sp
64349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R15); // lr
65349cc55cSDimitry Andric
66349cc55cSDimitry Andric if (!STI.hasHighRegisters()) {
67349cc55cSDimitry Andric for (unsigned i = 0; i < 10; i++)
68349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R16 + i); // R16 - R25
69349cc55cSDimitry Andric }
70349cc55cSDimitry Andric
71349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R26);
72349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R27);
73349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R28); // gp
74349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R29);
75349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R30);
76349cc55cSDimitry Andric markSuperRegs(Reserved, CSKY::R31); // tp
77349cc55cSDimitry Andric
78349cc55cSDimitry Andric assert(checkAllSuperRegsMarked(Reserved));
79349cc55cSDimitry Andric return Reserved;
80349cc55cSDimitry Andric }
81349cc55cSDimitry Andric
getNoPreservedMask() const82349cc55cSDimitry Andric const uint32_t *CSKYRegisterInfo::getNoPreservedMask() const {
83349cc55cSDimitry Andric return CSR_NoRegs_RegMask;
84349cc55cSDimitry Andric }
85349cc55cSDimitry Andric
86349cc55cSDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const87349cc55cSDimitry Andric CSKYRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
88349cc55cSDimitry Andric const CSKYSubtarget &STI = MF->getSubtarget<CSKYSubtarget>();
89349cc55cSDimitry Andric if (MF->getFunction().hasFnAttribute("interrupt")) {
9081ad6265SDimitry Andric if (STI.hasFPUv3DoubleFloat())
9181ad6265SDimitry Andric return CSR_GPR_FPR64v3_ISR_SaveList;
9281ad6265SDimitry Andric if (STI.hasFPUv3SingleFloat())
9381ad6265SDimitry Andric return CSR_GPR_FPR32v3_ISR_SaveList;
9481ad6265SDimitry Andric if (STI.hasFPUv2DoubleFloat())
9581ad6265SDimitry Andric return CSR_GPR_FPR64_ISR_SaveList;
9681ad6265SDimitry Andric if (STI.hasFPUv2SingleFloat())
9781ad6265SDimitry Andric return CSR_GPR_FPR32_ISR_SaveList;
98349cc55cSDimitry Andric return CSR_GPR_ISR_SaveList;
99349cc55cSDimitry Andric }
100349cc55cSDimitry Andric
10181ad6265SDimitry Andric if (STI.hasFPUv2DoubleFloat() || STI.hasFPUv3DoubleFloat())
10281ad6265SDimitry Andric return CSR_GPR_FPR64_SaveList;
10381ad6265SDimitry Andric if (STI.hasFPUv2SingleFloat() || STI.hasFPUv3SingleFloat())
10481ad6265SDimitry Andric return CSR_GPR_FPR32_SaveList;
105349cc55cSDimitry Andric return CSR_I32_SaveList;
106349cc55cSDimitry Andric }
107349cc55cSDimitry Andric
IsLegalOffset(const CSKYInstrInfo * TII,MachineInstr * MI,int & Offset)1080eae32dcSDimitry Andric static bool IsLegalOffset(const CSKYInstrInfo *TII, MachineInstr *MI,
1090eae32dcSDimitry Andric int &Offset) {
1100eae32dcSDimitry Andric const MCInstrDesc &Desc = MI->getDesc();
1110eae32dcSDimitry Andric unsigned AddrMode = (Desc.TSFlags & CSKYII::AddrModeMask);
1120eae32dcSDimitry Andric unsigned i = 0;
1130eae32dcSDimitry Andric for (; !MI->getOperand(i).isFI(); ++i) {
1140eae32dcSDimitry Andric assert(i + 1 < MI->getNumOperands() &&
1150eae32dcSDimitry Andric "Instr doesn't have FrameIndex operand!");
1160eae32dcSDimitry Andric }
1170eae32dcSDimitry Andric
1180eae32dcSDimitry Andric if (MI->getOpcode() == CSKY::ADDI32) {
1190eae32dcSDimitry Andric if (!isUInt<12>(std::abs(Offset) - 1))
1200eae32dcSDimitry Andric return false;
1210eae32dcSDimitry Andric if (Offset < 0) {
1220eae32dcSDimitry Andric MI->setDesc(TII->get(CSKY::SUBI32));
1230eae32dcSDimitry Andric Offset = -Offset;
1240eae32dcSDimitry Andric }
1250eae32dcSDimitry Andric
1260eae32dcSDimitry Andric return true;
1270eae32dcSDimitry Andric }
1280eae32dcSDimitry Andric
1290eae32dcSDimitry Andric if (MI->getOpcode() == CSKY::ADDI16XZ)
1300eae32dcSDimitry Andric return false;
1310eae32dcSDimitry Andric
1320eae32dcSDimitry Andric if (Offset < 0)
1330eae32dcSDimitry Andric return false;
1340eae32dcSDimitry Andric
1350eae32dcSDimitry Andric unsigned NumBits = 0;
1360eae32dcSDimitry Andric unsigned Scale = 1;
1370eae32dcSDimitry Andric switch (AddrMode) {
1380eae32dcSDimitry Andric case CSKYII::AddrMode32B:
1390eae32dcSDimitry Andric Scale = 1;
1400eae32dcSDimitry Andric NumBits = 12;
1410eae32dcSDimitry Andric break;
1420eae32dcSDimitry Andric case CSKYII::AddrMode32H:
1430eae32dcSDimitry Andric Scale = 2;
1440eae32dcSDimitry Andric NumBits = 12;
1450eae32dcSDimitry Andric break;
1460eae32dcSDimitry Andric case CSKYII::AddrMode32WD:
1470eae32dcSDimitry Andric Scale = 4;
1480eae32dcSDimitry Andric NumBits = 12;
1490eae32dcSDimitry Andric break;
1500eae32dcSDimitry Andric case CSKYII::AddrMode16B:
1510eae32dcSDimitry Andric Scale = 1;
1520eae32dcSDimitry Andric NumBits = 5;
1530eae32dcSDimitry Andric break;
1540eae32dcSDimitry Andric case CSKYII::AddrMode16H:
1550eae32dcSDimitry Andric Scale = 2;
1560eae32dcSDimitry Andric NumBits = 5;
1570eae32dcSDimitry Andric break;
1580eae32dcSDimitry Andric case CSKYII::AddrMode16W:
1590eae32dcSDimitry Andric Scale = 4;
1600eae32dcSDimitry Andric NumBits = 5;
1610eae32dcSDimitry Andric break;
1620eae32dcSDimitry Andric case CSKYII::AddrMode32SDF:
1630eae32dcSDimitry Andric Scale = 4;
1640eae32dcSDimitry Andric NumBits = 8;
1650eae32dcSDimitry Andric break;
1660eae32dcSDimitry Andric default:
1670eae32dcSDimitry Andric llvm_unreachable("Unsupported addressing mode!");
1680eae32dcSDimitry Andric }
1690eae32dcSDimitry Andric
1700eae32dcSDimitry Andric // Cannot encode offset.
1710eae32dcSDimitry Andric if ((Offset & (Scale - 1)) != 0)
1720eae32dcSDimitry Andric return false;
1730eae32dcSDimitry Andric
1740eae32dcSDimitry Andric unsigned Mask = (1 << NumBits) - 1;
1750eae32dcSDimitry Andric if ((unsigned)Offset <= Mask * Scale)
1760eae32dcSDimitry Andric return true;
1770eae32dcSDimitry Andric
1780eae32dcSDimitry Andric // Offset out of range.
1790eae32dcSDimitry Andric return false;
1800eae32dcSDimitry Andric }
1810eae32dcSDimitry Andric
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const182*bdd1243dSDimitry Andric bool CSKYRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
183349cc55cSDimitry Andric int SPAdj, unsigned FIOperandNum,
184349cc55cSDimitry Andric RegScavenger *RS) const {
185349cc55cSDimitry Andric assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
1860eae32dcSDimitry Andric
1870eae32dcSDimitry Andric MachineInstr *MI = &*II;
1880eae32dcSDimitry Andric MachineBasicBlock &MBB = *MI->getParent();
1890eae32dcSDimitry Andric MachineFunction &MF = *MI->getParent()->getParent();
1900eae32dcSDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
1910eae32dcSDimitry Andric const CSKYInstrInfo *TII = MF.getSubtarget<CSKYSubtarget>().getInstrInfo();
1920eae32dcSDimitry Andric DebugLoc DL = MI->getDebugLoc();
1930eae32dcSDimitry Andric const CSKYSubtarget &STI = MF.getSubtarget<CSKYSubtarget>();
1940eae32dcSDimitry Andric
1950eae32dcSDimitry Andric switch (MI->getOpcode()) {
1960eae32dcSDimitry Andric default:
1970eae32dcSDimitry Andric break;
1980eae32dcSDimitry Andric case CSKY::RESTORE_CARRY: {
1990eae32dcSDimitry Andric Register NewReg = STI.hasE2()
2000eae32dcSDimitry Andric ? MRI.createVirtualRegister(&CSKY::GPRRegClass)
2010eae32dcSDimitry Andric : MRI.createVirtualRegister(&CSKY::mGPRRegClass);
2020eae32dcSDimitry Andric
2030eae32dcSDimitry Andric auto *Temp = BuildMI(MBB, II, DL, TII->get(CSKY::LD32W), NewReg)
2040eae32dcSDimitry Andric .add(MI->getOperand(1))
2050eae32dcSDimitry Andric .add(MI->getOperand(2))
2060eae32dcSDimitry Andric .getInstr();
2070eae32dcSDimitry Andric
2080eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(STI.hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16),
2090eae32dcSDimitry Andric MI->getOperand(0).getReg())
2100eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true))
2110eae32dcSDimitry Andric .addImm(0);
2120eae32dcSDimitry Andric
2130eae32dcSDimitry Andric MI = Temp;
2140eae32dcSDimitry Andric
2150eae32dcSDimitry Andric MBB.erase(II);
2160eae32dcSDimitry Andric break;
2170eae32dcSDimitry Andric }
2180eae32dcSDimitry Andric case CSKY::SPILL_CARRY: {
2190eae32dcSDimitry Andric Register NewReg;
2200eae32dcSDimitry Andric if (STI.hasE2()) {
2210eae32dcSDimitry Andric NewReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
2220eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::MVC32), NewReg)
2230eae32dcSDimitry Andric .add(MI->getOperand(0));
2240eae32dcSDimitry Andric } else {
2250eae32dcSDimitry Andric NewReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
2260eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::MOVI16), NewReg).addImm(0);
2270eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::ADDC16))
2280eae32dcSDimitry Andric .addReg(NewReg, RegState::Define)
2290eae32dcSDimitry Andric .addReg(MI->getOperand(0).getReg(), RegState::Define)
2300eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true))
2310eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true))
2320eae32dcSDimitry Andric .addReg(MI->getOperand(0).getReg());
2330eae32dcSDimitry Andric
2340eae32dcSDimitry Andric BuildMI(MBB, II, DL, TII->get(CSKY::BTSTI16), MI->getOperand(0).getReg())
2350eae32dcSDimitry Andric .addReg(NewReg)
2360eae32dcSDimitry Andric .addImm(0);
2370eae32dcSDimitry Andric }
2380eae32dcSDimitry Andric
2390eae32dcSDimitry Andric MI = BuildMI(MBB, II, DL, TII->get(CSKY::ST32W))
2400eae32dcSDimitry Andric .addReg(NewReg, getKillRegState(true))
2410eae32dcSDimitry Andric .add(MI->getOperand(1))
2420eae32dcSDimitry Andric .add(MI->getOperand(2))
2430eae32dcSDimitry Andric .getInstr();
2440eae32dcSDimitry Andric
2450eae32dcSDimitry Andric MBB.erase(II);
2460eae32dcSDimitry Andric
2470eae32dcSDimitry Andric break;
2480eae32dcSDimitry Andric }
2490eae32dcSDimitry Andric }
2500eae32dcSDimitry Andric
2510eae32dcSDimitry Andric int FrameIndex = MI->getOperand(FIOperandNum).getIndex();
2520eae32dcSDimitry Andric Register FrameReg;
2530eae32dcSDimitry Andric int Offset = getFrameLowering(MF)
2540eae32dcSDimitry Andric ->getFrameIndexReference(MF, FrameIndex, FrameReg)
2550eae32dcSDimitry Andric .getFixed() +
2560eae32dcSDimitry Andric MI->getOperand(FIOperandNum + 1).getImm();
2570eae32dcSDimitry Andric
2580eae32dcSDimitry Andric if (!isInt<32>(Offset))
2590eae32dcSDimitry Andric report_fatal_error(
2600eae32dcSDimitry Andric "Frame offsets outside of the signed 32-bit range not supported");
2610eae32dcSDimitry Andric
2620eae32dcSDimitry Andric bool FrameRegIsKill = false;
2630eae32dcSDimitry Andric MachineBasicBlock::iterator NewII(MI);
2640eae32dcSDimitry Andric if (!IsLegalOffset(TII, MI, Offset)) {
2650eae32dcSDimitry Andric assert(isInt<32>(Offset) && "Int32 expected");
2660eae32dcSDimitry Andric // The offset won't fit in an immediate, so use a scratch register instead
2670eae32dcSDimitry Andric // Modify Offset and FrameReg appropriately
2680eae32dcSDimitry Andric Register ScratchReg = TII->movImm(MBB, NewII, DL, Offset);
2690eae32dcSDimitry Andric BuildMI(MBB, NewII, DL,
2700eae32dcSDimitry Andric TII->get(STI.hasE2() ? CSKY::ADDU32 : CSKY::ADDU16XZ), ScratchReg)
2710eae32dcSDimitry Andric .addReg(ScratchReg, RegState::Kill)
2720eae32dcSDimitry Andric .addReg(FrameReg);
2730eae32dcSDimitry Andric
2740eae32dcSDimitry Andric Offset = 0;
2750eae32dcSDimitry Andric FrameReg = ScratchReg;
2760eae32dcSDimitry Andric FrameRegIsKill = true;
2770eae32dcSDimitry Andric }
2780eae32dcSDimitry Andric
2790eae32dcSDimitry Andric if (Offset == 0 &&
2800eae32dcSDimitry Andric (MI->getOpcode() == CSKY::ADDI32 || MI->getOpcode() == CSKY::ADDI16XZ)) {
2810eae32dcSDimitry Andric MI->setDesc(TII->get(TargetOpcode::COPY));
2820eae32dcSDimitry Andric MI->getOperand(FIOperandNum)
2830eae32dcSDimitry Andric .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
28481ad6265SDimitry Andric MI->removeOperand(FIOperandNum + 1);
2850eae32dcSDimitry Andric } else {
2860eae32dcSDimitry Andric MI->getOperand(FIOperandNum)
2870eae32dcSDimitry Andric .ChangeToRegister(FrameReg, false, false, FrameRegIsKill);
2880eae32dcSDimitry Andric MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
2890eae32dcSDimitry Andric }
290*bdd1243dSDimitry Andric return false;
291349cc55cSDimitry Andric }
292