xref: /openbsd-src/gnu/llvm/llvm/lib/Target/M68k/M68kRegisterInfo.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
1*d415bd75Srobert //===-- M68kRegisterInfo.cpp - CPU0 Register Information --------*- C++ -*-===//
273471bf0Spatrick //
373471bf0Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
473471bf0Spatrick // See https://llvm.org/LICENSE.txt for license information.
573471bf0Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
673471bf0Spatrick //
773471bf0Spatrick //===----------------------------------------------------------------------===//
873471bf0Spatrick ///
973471bf0Spatrick /// \file
1073471bf0Spatrick /// This file contains the CPU0 implementation of the TargetRegisterInfo class.
1173471bf0Spatrick ///
1273471bf0Spatrick //===----------------------------------------------------------------------===//
1373471bf0Spatrick 
1473471bf0Spatrick #include "M68kRegisterInfo.h"
1573471bf0Spatrick 
1673471bf0Spatrick #include "M68k.h"
1773471bf0Spatrick #include "M68kMachineFunction.h"
1873471bf0Spatrick #include "M68kSubtarget.h"
1973471bf0Spatrick 
2073471bf0Spatrick #include "MCTargetDesc/M68kMCTargetDesc.h"
2173471bf0Spatrick 
22*d415bd75Srobert #include "llvm/CodeGen/MachineFrameInfo.h"
2373471bf0Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2473471bf0Spatrick #include "llvm/IR/Function.h"
2573471bf0Spatrick #include "llvm/IR/Type.h"
2673471bf0Spatrick #include "llvm/Support/CommandLine.h"
2773471bf0Spatrick #include "llvm/Support/Debug.h"
2873471bf0Spatrick #include "llvm/Support/ErrorHandling.h"
2973471bf0Spatrick #include "llvm/Support/raw_ostream.h"
3073471bf0Spatrick 
3173471bf0Spatrick #define GET_REGINFO_TARGET_DESC
3273471bf0Spatrick #include "M68kGenRegisterInfo.inc"
3373471bf0Spatrick 
3473471bf0Spatrick #define DEBUG_TYPE "m68k-reg-info"
3573471bf0Spatrick 
3673471bf0Spatrick using namespace llvm;
3773471bf0Spatrick 
3873471bf0Spatrick static cl::opt<bool> EnableBasePointer(
3973471bf0Spatrick     "m68k-use-base-pointer", cl::Hidden, cl::init(true),
4073471bf0Spatrick     cl::desc("Enable use of a base pointer for complex stack frames"));
4173471bf0Spatrick 
4273471bf0Spatrick // Pin the vtable to this file.
anchor()4373471bf0Spatrick void M68kRegisterInfo::anchor() {}
4473471bf0Spatrick 
M68kRegisterInfo(const M68kSubtarget & ST)4573471bf0Spatrick M68kRegisterInfo::M68kRegisterInfo(const M68kSubtarget &ST)
4673471bf0Spatrick     // FIXME x26 not sure it this the correct value, it expects RA, but M68k
4773471bf0Spatrick     // passes IP anyway, how this works?
4873471bf0Spatrick     : M68kGenRegisterInfo(M68k::A0, 0, 0, M68k::PC), Subtarget(ST) {
4973471bf0Spatrick   StackPtr = M68k::SP;
5073471bf0Spatrick   FramePtr = M68k::A6;
5173471bf0Spatrick   GlobalBasePtr = M68k::A5;
5273471bf0Spatrick   BasePtr = M68k::A4;
5373471bf0Spatrick }
5473471bf0Spatrick 
5573471bf0Spatrick //===----------------------------------------------------------------------===//
5673471bf0Spatrick // Callee Saved Registers methods
5773471bf0Spatrick //===----------------------------------------------------------------------===//
5873471bf0Spatrick 
5973471bf0Spatrick const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const6073471bf0Spatrick M68kRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
6173471bf0Spatrick   return CSR_STD_SaveList;
6273471bf0Spatrick }
6373471bf0Spatrick 
6473471bf0Spatrick const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID) const6573471bf0Spatrick M68kRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
6673471bf0Spatrick                                        CallingConv::ID) const {
6773471bf0Spatrick   return CSR_STD_RegMask;
6873471bf0Spatrick }
6973471bf0Spatrick 
7073471bf0Spatrick const TargetRegisterClass *
getRegsForTailCall(const MachineFunction & MF) const7173471bf0Spatrick M68kRegisterInfo::getRegsForTailCall(const MachineFunction &MF) const {
7273471bf0Spatrick   return &M68k::XR32_TCRegClass;
7373471bf0Spatrick }
7473471bf0Spatrick 
7573471bf0Spatrick unsigned
getMatchingMegaReg(unsigned Reg,const TargetRegisterClass * RC) const7673471bf0Spatrick M68kRegisterInfo::getMatchingMegaReg(unsigned Reg,
7773471bf0Spatrick                                      const TargetRegisterClass *RC) const {
7873471bf0Spatrick   for (MCSuperRegIterator Super(Reg, this); Super.isValid(); ++Super)
7973471bf0Spatrick     if (RC->contains(*Super))
8073471bf0Spatrick       return *Super;
8173471bf0Spatrick   return 0;
8273471bf0Spatrick }
8373471bf0Spatrick 
8473471bf0Spatrick const TargetRegisterClass *
getMaximalPhysRegClass(unsigned reg,MVT VT) const8573471bf0Spatrick M68kRegisterInfo::getMaximalPhysRegClass(unsigned reg, MVT VT) const {
8673471bf0Spatrick   assert(Register::isPhysicalRegister(reg) &&
8773471bf0Spatrick          "reg must be a physical register");
8873471bf0Spatrick 
8973471bf0Spatrick   // Pick the most sub register class of the right type that contains
9073471bf0Spatrick   // this physreg.
9173471bf0Spatrick   const TargetRegisterClass *BestRC = nullptr;
9273471bf0Spatrick   for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E;
9373471bf0Spatrick        ++I) {
9473471bf0Spatrick     const TargetRegisterClass *RC = *I;
9573471bf0Spatrick     if ((VT == MVT::Other || isTypeLegalForClass(*RC, VT)) &&
9673471bf0Spatrick         RC->contains(reg) &&
9773471bf0Spatrick         (!BestRC ||
9873471bf0Spatrick          (BestRC->hasSubClass(RC) && RC->getNumRegs() > BestRC->getNumRegs())))
9973471bf0Spatrick       BestRC = RC;
10073471bf0Spatrick   }
10173471bf0Spatrick 
10273471bf0Spatrick   assert(BestRC && "Couldn't find the register class");
10373471bf0Spatrick   return BestRC;
10473471bf0Spatrick }
10573471bf0Spatrick 
getRegisterOrder(unsigned Reg,const TargetRegisterClass & TRC) const10673471bf0Spatrick int M68kRegisterInfo::getRegisterOrder(unsigned Reg,
10773471bf0Spatrick                                        const TargetRegisterClass &TRC) const {
10873471bf0Spatrick   for (unsigned i = 0; i < TRC.getNumRegs(); ++i) {
10973471bf0Spatrick     if (regsOverlap(Reg, TRC.getRegister(i))) {
11073471bf0Spatrick       return i;
11173471bf0Spatrick     }
11273471bf0Spatrick   }
11373471bf0Spatrick   return -1;
11473471bf0Spatrick }
11573471bf0Spatrick 
getSpillRegisterOrder(unsigned Reg) const11673471bf0Spatrick int M68kRegisterInfo::getSpillRegisterOrder(unsigned Reg) const {
11773471bf0Spatrick   int Result = getRegisterOrder(Reg, *getRegClass(M68k::SPILLRegClassID));
11873471bf0Spatrick   assert(Result >= 0 && "Can not determine spill order");
11973471bf0Spatrick   return Result;
12073471bf0Spatrick }
12173471bf0Spatrick 
getReservedRegs(const MachineFunction & MF) const12273471bf0Spatrick BitVector M68kRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
12373471bf0Spatrick   const M68kFrameLowering *TFI = getFrameLowering(MF);
12473471bf0Spatrick 
12573471bf0Spatrick   BitVector Reserved(getNumRegs());
12673471bf0Spatrick 
12773471bf0Spatrick   // Set a register's and its sub-registers and aliases as reserved.
12873471bf0Spatrick   auto setBitVector = [&Reserved, this](unsigned Reg) {
12973471bf0Spatrick     for (MCRegAliasIterator I(Reg, this, /* self */ true); I.isValid(); ++I) {
13073471bf0Spatrick       Reserved.set(*I);
13173471bf0Spatrick     }
13273471bf0Spatrick     for (MCSubRegIterator I(Reg, this, /* self */ true); I.isValid(); ++I) {
13373471bf0Spatrick       Reserved.set(*I);
13473471bf0Spatrick     }
13573471bf0Spatrick   };
13673471bf0Spatrick 
13773471bf0Spatrick   // Registers reserved by users
13873471bf0Spatrick   for (size_t Reg = 0, Total = getNumRegs(); Reg != Total; ++Reg) {
13973471bf0Spatrick     if (MF.getSubtarget<M68kSubtarget>().isRegisterReservedByUser(Reg))
14073471bf0Spatrick       setBitVector(Reg);
14173471bf0Spatrick   }
14273471bf0Spatrick 
14373471bf0Spatrick   setBitVector(M68k::PC);
14473471bf0Spatrick   setBitVector(M68k::SP);
14573471bf0Spatrick 
14673471bf0Spatrick   if (TFI->hasFP(MF)) {
14773471bf0Spatrick     setBitVector(FramePtr);
14873471bf0Spatrick   }
14973471bf0Spatrick 
15073471bf0Spatrick   // Set the base-pointer register and its aliases as reserved if needed.
15173471bf0Spatrick   if (hasBasePointer(MF)) {
15273471bf0Spatrick     CallingConv::ID CC = MF.getFunction().getCallingConv();
15373471bf0Spatrick     const uint32_t *RegMask = getCallPreservedMask(MF, CC);
15473471bf0Spatrick     if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister()))
15573471bf0Spatrick       report_fatal_error("Stack realignment in presence of dynamic allocas is "
15673471bf0Spatrick                          "not supported with"
15773471bf0Spatrick                          "this calling convention.");
15873471bf0Spatrick 
15973471bf0Spatrick     setBitVector(getBaseRegister());
16073471bf0Spatrick   }
16173471bf0Spatrick 
16273471bf0Spatrick   return Reserved;
16373471bf0Spatrick }
16473471bf0Spatrick 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const165*d415bd75Srobert bool M68kRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
16673471bf0Spatrick                                            int SPAdj, unsigned FIOperandNum,
16773471bf0Spatrick                                            RegScavenger *RS) const {
16873471bf0Spatrick   MachineInstr &MI = *II;
16973471bf0Spatrick   MachineFunction &MF = *MI.getParent()->getParent();
17073471bf0Spatrick   const M68kFrameLowering *TFI = getFrameLowering(MF);
17173471bf0Spatrick 
17273471bf0Spatrick   // We have either (i,An,Rn) or (i,An) EA form
17373471bf0Spatrick   // NOTE Base contains the FI and we need to backtrace a bit to get Disp
17473471bf0Spatrick   MachineOperand &Disp = MI.getOperand(FIOperandNum - 1);
17573471bf0Spatrick   MachineOperand &Base = MI.getOperand(FIOperandNum);
17673471bf0Spatrick 
17773471bf0Spatrick   int Imm = (int)(Disp.getImm());
17873471bf0Spatrick   int FIndex = (int)(Base.getIndex());
17973471bf0Spatrick 
18073471bf0Spatrick   // FIXME tail call: implement jmp from mem
18173471bf0Spatrick   bool AfterFPPop = false;
18273471bf0Spatrick 
18373471bf0Spatrick   unsigned BasePtr;
18473471bf0Spatrick   if (hasBasePointer(MF))
18573471bf0Spatrick     BasePtr = (FIndex < 0 ? FramePtr : getBaseRegister());
18673471bf0Spatrick   else if (hasStackRealignment(MF))
18773471bf0Spatrick     BasePtr = (FIndex < 0 ? FramePtr : StackPtr);
18873471bf0Spatrick   else if (AfterFPPop)
18973471bf0Spatrick     BasePtr = StackPtr;
19073471bf0Spatrick   else
19173471bf0Spatrick     BasePtr = (TFI->hasFP(MF) ? FramePtr : StackPtr);
19273471bf0Spatrick 
19373471bf0Spatrick   Base.ChangeToRegister(BasePtr, false);
19473471bf0Spatrick 
19573471bf0Spatrick   // Now add the frame object offset to the offset from FP.
19673471bf0Spatrick   int64_t FIOffset;
19773471bf0Spatrick   Register IgnoredFrameReg;
19873471bf0Spatrick   if (AfterFPPop) {
19973471bf0Spatrick     // Tail call jmp happens after FP is popped.
20073471bf0Spatrick     const MachineFrameInfo &MFI = MF.getFrameInfo();
20173471bf0Spatrick     FIOffset = MFI.getObjectOffset(FIndex) - TFI->getOffsetOfLocalArea();
20273471bf0Spatrick   } else {
20373471bf0Spatrick     FIOffset =
20473471bf0Spatrick         TFI->getFrameIndexReference(MF, FIndex, IgnoredFrameReg).getFixed();
20573471bf0Spatrick   }
20673471bf0Spatrick 
20773471bf0Spatrick   if (BasePtr == StackPtr)
20873471bf0Spatrick     FIOffset += SPAdj;
20973471bf0Spatrick 
21073471bf0Spatrick   Disp.ChangeToImmediate(FIOffset + Imm);
211*d415bd75Srobert   return false;
21273471bf0Spatrick }
21373471bf0Spatrick 
requiresRegisterScavenging(const MachineFunction & MF) const21473471bf0Spatrick bool M68kRegisterInfo::requiresRegisterScavenging(
21573471bf0Spatrick     const MachineFunction &MF) const {
21673471bf0Spatrick   return true;
21773471bf0Spatrick }
21873471bf0Spatrick 
trackLivenessAfterRegAlloc(const MachineFunction & MF) const21973471bf0Spatrick bool M68kRegisterInfo::trackLivenessAfterRegAlloc(
22073471bf0Spatrick     const MachineFunction &MF) const {
22173471bf0Spatrick   return true;
22273471bf0Spatrick }
22373471bf0Spatrick 
CantUseSP(const MachineFrameInfo & MFI)22473471bf0Spatrick static bool CantUseSP(const MachineFrameInfo &MFI) {
22573471bf0Spatrick   return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment();
22673471bf0Spatrick }
22773471bf0Spatrick 
hasBasePointer(const MachineFunction & MF) const22873471bf0Spatrick bool M68kRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
22973471bf0Spatrick   const MachineFrameInfo &MFI = MF.getFrameInfo();
23073471bf0Spatrick 
23173471bf0Spatrick   if (!EnableBasePointer)
23273471bf0Spatrick     return false;
23373471bf0Spatrick 
23473471bf0Spatrick   // When we need stack realignment, we can't address the stack from the frame
23573471bf0Spatrick   // pointer.  When we have dynamic allocas or stack-adjusting inline asm, we
23673471bf0Spatrick   // can't address variables from the stack pointer.  MS inline asm can
23773471bf0Spatrick   // reference locals while also adjusting the stack pointer.  When we can't
23873471bf0Spatrick   // use both the SP and the FP, we need a separate base pointer register.
23973471bf0Spatrick   bool CantUseFP = hasStackRealignment(MF);
24073471bf0Spatrick   return CantUseFP && CantUseSP(MFI);
24173471bf0Spatrick }
24273471bf0Spatrick 
canRealignStack(const MachineFunction & MF) const24373471bf0Spatrick bool M68kRegisterInfo::canRealignStack(const MachineFunction &MF) const {
24473471bf0Spatrick   if (!TargetRegisterInfo::canRealignStack(MF))
24573471bf0Spatrick     return false;
24673471bf0Spatrick 
24773471bf0Spatrick   const MachineFrameInfo &MFI = MF.getFrameInfo();
24873471bf0Spatrick   const MachineRegisterInfo *MRI = &MF.getRegInfo();
24973471bf0Spatrick 
25073471bf0Spatrick   // Stack realignment requires a frame pointer.  If we already started
25173471bf0Spatrick   // register allocation with frame pointer elimination, it is too late now.
25273471bf0Spatrick   if (!MRI->canReserveReg(FramePtr))
25373471bf0Spatrick     return false;
25473471bf0Spatrick 
25573471bf0Spatrick   // If a base pointer is necessary. Check that it isn't too late to reserve it.
25673471bf0Spatrick   if (CantUseSP(MFI))
25773471bf0Spatrick     return MRI->canReserveReg(BasePtr);
25873471bf0Spatrick 
25973471bf0Spatrick   return true;
26073471bf0Spatrick }
26173471bf0Spatrick 
getFrameRegister(const MachineFunction & MF) const26273471bf0Spatrick Register M68kRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
26373471bf0Spatrick   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
26473471bf0Spatrick   return TFI->hasFP(MF) ? FramePtr : StackPtr;
26573471bf0Spatrick }
26673471bf0Spatrick 
intRegClass(unsigned size) const26773471bf0Spatrick const TargetRegisterClass *M68kRegisterInfo::intRegClass(unsigned size) const {
26873471bf0Spatrick   return &M68k::DR32RegClass;
26973471bf0Spatrick }
270