xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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