12d1f6d67SPete Couperus //===- ARCRegisterInfo.cpp - ARC Register Information -----------*- C++ -*-===//
22d1f6d67SPete Couperus //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62d1f6d67SPete Couperus //
72d1f6d67SPete Couperus //===----------------------------------------------------------------------===//
82d1f6d67SPete Couperus //
92d1f6d67SPete Couperus // This file contains the ARC implementation of the MRegisterInfo class.
102d1f6d67SPete Couperus //
112d1f6d67SPete Couperus //===----------------------------------------------------------------------===//
122d1f6d67SPete Couperus
132d1f6d67SPete Couperus #include "ARCRegisterInfo.h"
142d1f6d67SPete Couperus #include "ARC.h"
152d1f6d67SPete Couperus #include "ARCInstrInfo.h"
162d1f6d67SPete Couperus #include "ARCMachineFunctionInfo.h"
172d1f6d67SPete Couperus #include "ARCSubtarget.h"
182d1f6d67SPete Couperus #include "llvm/ADT/BitVector.h"
192d1f6d67SPete Couperus #include "llvm/CodeGen/MachineFrameInfo.h"
202d1f6d67SPete Couperus #include "llvm/CodeGen/MachineFunction.h"
212d1f6d67SPete Couperus #include "llvm/CodeGen/MachineInstrBuilder.h"
222d1f6d67SPete Couperus #include "llvm/CodeGen/MachineModuleInfo.h"
232d1f6d67SPete Couperus #include "llvm/CodeGen/MachineRegisterInfo.h"
242d1f6d67SPete Couperus #include "llvm/CodeGen/RegisterScavenging.h"
25ecd15fbfSGraham Yiu #include "llvm/CodeGen/TargetFrameLowering.h"
262d1f6d67SPete Couperus #include "llvm/IR/Function.h"
272d1f6d67SPete Couperus #include "llvm/Support/Debug.h"
282d1f6d67SPete Couperus #include "llvm/Target/TargetMachine.h"
292d1f6d67SPete Couperus #include "llvm/Target/TargetOptions.h"
302d1f6d67SPete Couperus
312d1f6d67SPete Couperus using namespace llvm;
322d1f6d67SPete Couperus
332d1f6d67SPete Couperus #define DEBUG_TYPE "arc-reg-info"
342d1f6d67SPete Couperus
352d1f6d67SPete Couperus #define GET_REGINFO_TARGET_DESC
362d1f6d67SPete Couperus #include "ARCGenRegisterInfo.inc"
372d1f6d67SPete Couperus
replaceFrameIndex(MachineBasicBlock::iterator II,const ARCInstrInfo & TII,unsigned Reg,unsigned FrameReg,int Offset,int StackSize,int ObjSize,RegScavenger * RS,int SPAdj)38*417f8ea4SMark Schimmel static void replaceFrameIndex(MachineBasicBlock::iterator II,
392d1f6d67SPete Couperus const ARCInstrInfo &TII, unsigned Reg,
402d1f6d67SPete Couperus unsigned FrameReg, int Offset, int StackSize,
412d1f6d67SPete Couperus int ObjSize, RegScavenger *RS, int SPAdj) {
422d1f6d67SPete Couperus assert(RS && "Need register scavenger.");
432d1f6d67SPete Couperus MachineInstr &MI = *II;
442d1f6d67SPete Couperus MachineBasicBlock &MBB = *MI.getParent();
45*417f8ea4SMark Schimmel DebugLoc DL = MI.getDebugLoc();
462d1f6d67SPete Couperus unsigned BaseReg = FrameReg;
472d1f6d67SPete Couperus unsigned KillState = 0;
482d1f6d67SPete Couperus if (MI.getOpcode() == ARC::LD_rs9 && (Offset >= 256 || Offset < -256)) {
492d1f6d67SPete Couperus // Loads can always be reached with LD_rlimm.
50*417f8ea4SMark Schimmel BuildMI(MBB, II, DL, TII.get(ARC::LD_rlimm), Reg)
512d1f6d67SPete Couperus .addReg(BaseReg)
522d1f6d67SPete Couperus .addImm(Offset)
532d1f6d67SPete Couperus .addMemOperand(*MI.memoperands_begin());
542d1f6d67SPete Couperus MBB.erase(II);
552d1f6d67SPete Couperus return;
562d1f6d67SPete Couperus }
572d1f6d67SPete Couperus
582d1f6d67SPete Couperus if (MI.getOpcode() != ARC::GETFI && (Offset >= 256 || Offset < -256)) {
592d1f6d67SPete Couperus // We need to use a scratch register to reach the far-away frame indexes.
602d1f6d67SPete Couperus BaseReg = RS->FindUnusedReg(&ARC::GPR32RegClass);
612d1f6d67SPete Couperus if (!BaseReg) {
622d1f6d67SPete Couperus // We can be sure that the scavenged-register slot is within the range
632d1f6d67SPete Couperus // of the load offset.
642d1f6d67SPete Couperus const TargetRegisterInfo *TRI =
652d1f6d67SPete Couperus MBB.getParent()->getSubtarget().getRegisterInfo();
662d1f6d67SPete Couperus BaseReg = RS->scavengeRegister(&ARC::GPR32RegClass, II, SPAdj);
672d1f6d67SPete Couperus assert(BaseReg && "Register scavenging failed.");
68d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Scavenged register " << printReg(BaseReg, TRI)
699d419d3bSFrancis Visoiu Mistrih << " for FrameReg=" << printReg(FrameReg, TRI)
702d1f6d67SPete Couperus << "+Offset=" << Offset << "\n");
712d1f6d67SPete Couperus (void)TRI;
722d1f6d67SPete Couperus RS->setRegUsed(BaseReg);
732d1f6d67SPete Couperus }
742d1f6d67SPete Couperus unsigned AddOpc = isUInt<6>(Offset) ? ARC::ADD_rru6 : ARC::ADD_rrlimm;
75*417f8ea4SMark Schimmel BuildMI(MBB, II, DL, TII.get(AddOpc))
762d1f6d67SPete Couperus .addReg(BaseReg, RegState::Define)
772d1f6d67SPete Couperus .addReg(FrameReg)
782d1f6d67SPete Couperus .addImm(Offset);
792d1f6d67SPete Couperus Offset = 0;
802d1f6d67SPete Couperus KillState = RegState::Kill;
812d1f6d67SPete Couperus }
822d1f6d67SPete Couperus switch (MI.getOpcode()) {
832d1f6d67SPete Couperus case ARC::LD_rs9:
842d1f6d67SPete Couperus assert((Offset % 4 == 0) && "LD needs 4 byte alignment.");
85f8f1ace5SMatt Arsenault LLVM_FALLTHROUGH;
862d1f6d67SPete Couperus case ARC::LDH_rs9:
872d1f6d67SPete Couperus case ARC::LDH_X_rs9:
882d1f6d67SPete Couperus assert((Offset % 2 == 0) && "LDH needs 2 byte alignment.");
89f8f1ace5SMatt Arsenault LLVM_FALLTHROUGH;
902d1f6d67SPete Couperus case ARC::LDB_rs9:
912d1f6d67SPete Couperus case ARC::LDB_X_rs9:
92d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Building LDFI\n");
93*417f8ea4SMark Schimmel BuildMI(MBB, II, DL, TII.get(MI.getOpcode()), Reg)
942d1f6d67SPete Couperus .addReg(BaseReg, KillState)
952d1f6d67SPete Couperus .addImm(Offset)
962d1f6d67SPete Couperus .addMemOperand(*MI.memoperands_begin());
972d1f6d67SPete Couperus break;
982d1f6d67SPete Couperus case ARC::ST_rs9:
992d1f6d67SPete Couperus assert((Offset % 4 == 0) && "ST needs 4 byte alignment.");
100f8f1ace5SMatt Arsenault LLVM_FALLTHROUGH;
1012d1f6d67SPete Couperus case ARC::STH_rs9:
1022d1f6d67SPete Couperus assert((Offset % 2 == 0) && "STH needs 2 byte alignment.");
103f8f1ace5SMatt Arsenault LLVM_FALLTHROUGH;
1042d1f6d67SPete Couperus case ARC::STB_rs9:
105d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Building STFI\n");
106*417f8ea4SMark Schimmel BuildMI(MBB, II, DL, TII.get(MI.getOpcode()))
1072d1f6d67SPete Couperus .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
1082d1f6d67SPete Couperus .addReg(BaseReg, KillState)
1092d1f6d67SPete Couperus .addImm(Offset)
1102d1f6d67SPete Couperus .addMemOperand(*MI.memoperands_begin());
1112d1f6d67SPete Couperus break;
1122d1f6d67SPete Couperus case ARC::GETFI:
113d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Building GETFI\n");
114*417f8ea4SMark Schimmel BuildMI(MBB, II, DL,
1152d1f6d67SPete Couperus TII.get(isUInt<6>(Offset) ? ARC::ADD_rru6 : ARC::ADD_rrlimm))
1162d1f6d67SPete Couperus .addReg(Reg, RegState::Define)
1172d1f6d67SPete Couperus .addReg(FrameReg)
1182d1f6d67SPete Couperus .addImm(Offset);
1192d1f6d67SPete Couperus break;
1202d1f6d67SPete Couperus default:
1212d1f6d67SPete Couperus llvm_unreachable("Unhandled opcode.");
1222d1f6d67SPete Couperus }
1232d1f6d67SPete Couperus
1242d1f6d67SPete Couperus // Erase old instruction.
1252d1f6d67SPete Couperus MBB.erase(II);
1262d1f6d67SPete Couperus }
1272d1f6d67SPete Couperus
ARCRegisterInfo(const ARCSubtarget & ST)128*417f8ea4SMark Schimmel ARCRegisterInfo::ARCRegisterInfo(const ARCSubtarget &ST)
129*417f8ea4SMark Schimmel : ARCGenRegisterInfo(ARC::BLINK), ST(ST) {}
1302d1f6d67SPete Couperus
needsFrameMoves(const MachineFunction & MF)1312d1f6d67SPete Couperus bool ARCRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
13292aa0c2dSDavid Candler return MF.needsFrameMoves();
1332d1f6d67SPete Couperus }
1342d1f6d67SPete Couperus
1352d1f6d67SPete Couperus const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const1362d1f6d67SPete Couperus ARCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
1372d1f6d67SPete Couperus return CSR_ARC_SaveList;
1382d1f6d67SPete Couperus }
1392d1f6d67SPete Couperus
getReservedRegs(const MachineFunction & MF) const1402d1f6d67SPete Couperus BitVector ARCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
1412d1f6d67SPete Couperus BitVector Reserved(getNumRegs());
1422d1f6d67SPete Couperus
1432d1f6d67SPete Couperus Reserved.set(ARC::ILINK);
1442d1f6d67SPete Couperus Reserved.set(ARC::SP);
1452d1f6d67SPete Couperus Reserved.set(ARC::GP);
1462d1f6d67SPete Couperus Reserved.set(ARC::R25);
1472d1f6d67SPete Couperus Reserved.set(ARC::BLINK);
1482d1f6d67SPete Couperus Reserved.set(ARC::FP);
149*417f8ea4SMark Schimmel
1502d1f6d67SPete Couperus return Reserved;
1512d1f6d67SPete Couperus }
1522d1f6d67SPete Couperus
requiresRegisterScavenging(const MachineFunction & MF) const1532d1f6d67SPete Couperus bool ARCRegisterInfo::requiresRegisterScavenging(
1542d1f6d67SPete Couperus const MachineFunction &MF) const {
1552d1f6d67SPete Couperus return true;
1562d1f6d67SPete Couperus }
1572d1f6d67SPete Couperus
useFPForScavengingIndex(const MachineFunction & MF) const1582d1f6d67SPete Couperus bool ARCRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
1592d1f6d67SPete Couperus return true;
1602d1f6d67SPete Couperus }
1612d1f6d67SPete Couperus
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const1622d1f6d67SPete Couperus void ARCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
1632d1f6d67SPete Couperus int SPAdj, unsigned FIOperandNum,
1642d1f6d67SPete Couperus RegScavenger *RS) const {
1652d1f6d67SPete Couperus assert(SPAdj == 0 && "Unexpected");
1662d1f6d67SPete Couperus MachineInstr &MI = *II;
1672d1f6d67SPete Couperus MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
1682d1f6d67SPete Couperus int FrameIndex = FrameOp.getIndex();
1692d1f6d67SPete Couperus
1702d1f6d67SPete Couperus MachineFunction &MF = *MI.getParent()->getParent();
1712d1f6d67SPete Couperus const ARCInstrInfo &TII = *MF.getSubtarget<ARCSubtarget>().getInstrInfo();
1722d1f6d67SPete Couperus const ARCFrameLowering *TFI = getFrameLowering(MF);
1732d1f6d67SPete Couperus int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);
1742d1f6d67SPete Couperus int ObjSize = MF.getFrameInfo().getObjectSize(FrameIndex);
1752d1f6d67SPete Couperus int StackSize = MF.getFrameInfo().getStackSize();
1762d1f6d67SPete Couperus int LocalFrameSize = MF.getFrameInfo().getLocalFrameSize();
1772d1f6d67SPete Couperus
178d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\nFunction : " << MF.getName() << "\n");
179d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "<--------->\n");
180d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << MI << "\n");
181d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "FrameIndex : " << FrameIndex << "\n");
182d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "ObjSize : " << ObjSize << "\n");
183d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "FrameOffset : " << Offset << "\n");
184d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "StackSize : " << StackSize << "\n");
185d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "LocalFrameSize : " << LocalFrameSize << "\n");
1862d1f6d67SPete Couperus (void)LocalFrameSize;
1872d1f6d67SPete Couperus
1882d1f6d67SPete Couperus // Special handling of DBG_VALUE instructions.
1892d1f6d67SPete Couperus if (MI.isDebugValue()) {
190e3a676e9SMatt Arsenault Register FrameReg = getFrameRegister(MF);
1912d1f6d67SPete Couperus MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
1922d1f6d67SPete Couperus MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
1932d1f6d67SPete Couperus return;
1942d1f6d67SPete Couperus }
1952d1f6d67SPete Couperus
1962d1f6d67SPete Couperus // fold constant into offset.
1972d1f6d67SPete Couperus Offset += MI.getOperand(FIOperandNum + 1).getImm();
1982d1f6d67SPete Couperus
1992d1f6d67SPete Couperus // TODO: assert based on the load type:
2002d1f6d67SPete Couperus // ldb needs no alignment,
2012d1f6d67SPete Couperus // ldh needs 2 byte alignment
2022d1f6d67SPete Couperus // ld needs 4 byte alignment
203d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Offset : " << Offset << "\n"
2042d1f6d67SPete Couperus << "<--------->\n");
2052d1f6d67SPete Couperus
2060c476111SDaniel Sanders Register Reg = MI.getOperand(0).getReg();
2072d1f6d67SPete Couperus assert(ARC::GPR32RegClass.contains(Reg) && "Unexpected register operand");
2082d1f6d67SPete Couperus
2092d1f6d67SPete Couperus if (!TFI->hasFP(MF)) {
2102d1f6d67SPete Couperus Offset = StackSize + Offset;
2112d1f6d67SPete Couperus if (FrameIndex >= 0)
2122d1f6d67SPete Couperus assert((Offset >= 0 && Offset < StackSize) && "SP Offset not in bounds.");
2132d1f6d67SPete Couperus } else {
2142d1f6d67SPete Couperus if (FrameIndex >= 0) {
2152d1f6d67SPete Couperus assert((Offset < 0 && -Offset <= StackSize) &&
2162d1f6d67SPete Couperus "FP Offset not in bounds.");
2172d1f6d67SPete Couperus }
2182d1f6d67SPete Couperus }
219*417f8ea4SMark Schimmel replaceFrameIndex(II, TII, Reg, getFrameRegister(MF), Offset, StackSize,
2202d1f6d67SPete Couperus ObjSize, RS, SPAdj);
2212d1f6d67SPete Couperus }
2222d1f6d67SPete Couperus
getFrameRegister(const MachineFunction & MF) const223e3a676e9SMatt Arsenault Register ARCRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
2242d1f6d67SPete Couperus const ARCFrameLowering *TFI = getFrameLowering(MF);
2252d1f6d67SPete Couperus return TFI->hasFP(MF) ? ARC::FP : ARC::SP;
2262d1f6d67SPete Couperus }
2272d1f6d67SPete Couperus
2282d1f6d67SPete Couperus const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const2292d1f6d67SPete Couperus ARCRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
2302d1f6d67SPete Couperus CallingConv::ID CC) const {
2312d1f6d67SPete Couperus return CSR_ARC_RegMask;
2322d1f6d67SPete Couperus }
233