xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/M68kRegisterInfo.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1*fe6060f1SDimitry Andric //===-- M68kRegisterInfo.cpp - CPU0 Register Information -----*- C++ -*--===//
2*fe6060f1SDimitry Andric //
3*fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*fe6060f1SDimitry Andric //
7*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8*fe6060f1SDimitry Andric ///
9*fe6060f1SDimitry Andric /// \file
10*fe6060f1SDimitry Andric /// This file contains the CPU0 implementation of the TargetRegisterInfo class.
11*fe6060f1SDimitry Andric ///
12*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
13*fe6060f1SDimitry Andric 
14*fe6060f1SDimitry Andric #include "M68kRegisterInfo.h"
15*fe6060f1SDimitry Andric 
16*fe6060f1SDimitry Andric #include "M68k.h"
17*fe6060f1SDimitry Andric #include "M68kMachineFunction.h"
18*fe6060f1SDimitry Andric #include "M68kSubtarget.h"
19*fe6060f1SDimitry Andric 
20*fe6060f1SDimitry Andric #include "MCTargetDesc/M68kMCTargetDesc.h"
21*fe6060f1SDimitry Andric 
22*fe6060f1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
23*fe6060f1SDimitry Andric #include "llvm/IR/Function.h"
24*fe6060f1SDimitry Andric #include "llvm/IR/Type.h"
25*fe6060f1SDimitry Andric #include "llvm/Support/CommandLine.h"
26*fe6060f1SDimitry Andric #include "llvm/Support/Debug.h"
27*fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
28*fe6060f1SDimitry Andric #include "llvm/Support/raw_ostream.h"
29*fe6060f1SDimitry Andric 
30*fe6060f1SDimitry Andric #define GET_REGINFO_TARGET_DESC
31*fe6060f1SDimitry Andric #include "M68kGenRegisterInfo.inc"
32*fe6060f1SDimitry Andric 
33*fe6060f1SDimitry Andric #define DEBUG_TYPE "m68k-reg-info"
34*fe6060f1SDimitry Andric 
35*fe6060f1SDimitry Andric using namespace llvm;
36*fe6060f1SDimitry Andric 
37*fe6060f1SDimitry Andric static cl::opt<bool> EnableBasePointer(
38*fe6060f1SDimitry Andric     "m68k-use-base-pointer", cl::Hidden, cl::init(true),
39*fe6060f1SDimitry Andric     cl::desc("Enable use of a base pointer for complex stack frames"));
40*fe6060f1SDimitry Andric 
41*fe6060f1SDimitry Andric // Pin the vtable to this file.
42*fe6060f1SDimitry Andric void M68kRegisterInfo::anchor() {}
43*fe6060f1SDimitry Andric 
44*fe6060f1SDimitry Andric M68kRegisterInfo::M68kRegisterInfo(const M68kSubtarget &ST)
45*fe6060f1SDimitry Andric     // FIXME x26 not sure it this the correct value, it expects RA, but M68k
46*fe6060f1SDimitry Andric     // passes IP anyway, how this works?
47*fe6060f1SDimitry Andric     : M68kGenRegisterInfo(M68k::A0, 0, 0, M68k::PC), Subtarget(ST) {
48*fe6060f1SDimitry Andric   StackPtr = M68k::SP;
49*fe6060f1SDimitry Andric   FramePtr = M68k::A6;
50*fe6060f1SDimitry Andric   GlobalBasePtr = M68k::A5;
51*fe6060f1SDimitry Andric   BasePtr = M68k::A4;
52*fe6060f1SDimitry Andric }
53*fe6060f1SDimitry Andric 
54*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
55*fe6060f1SDimitry Andric // Callee Saved Registers methods
56*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
57*fe6060f1SDimitry Andric 
58*fe6060f1SDimitry Andric const MCPhysReg *
59*fe6060f1SDimitry Andric M68kRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
60*fe6060f1SDimitry Andric   return CSR_STD_SaveList;
61*fe6060f1SDimitry Andric }
62*fe6060f1SDimitry Andric 
63*fe6060f1SDimitry Andric const uint32_t *
64*fe6060f1SDimitry Andric M68kRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
65*fe6060f1SDimitry Andric                                        CallingConv::ID) const {
66*fe6060f1SDimitry Andric   return CSR_STD_RegMask;
67*fe6060f1SDimitry Andric }
68*fe6060f1SDimitry Andric 
69*fe6060f1SDimitry Andric const TargetRegisterClass *
70*fe6060f1SDimitry Andric M68kRegisterInfo::getRegsForTailCall(const MachineFunction &MF) const {
71*fe6060f1SDimitry Andric   return &M68k::XR32_TCRegClass;
72*fe6060f1SDimitry Andric }
73*fe6060f1SDimitry Andric 
74*fe6060f1SDimitry Andric unsigned
75*fe6060f1SDimitry Andric M68kRegisterInfo::getMatchingMegaReg(unsigned Reg,
76*fe6060f1SDimitry Andric                                      const TargetRegisterClass *RC) const {
77*fe6060f1SDimitry Andric   for (MCSuperRegIterator Super(Reg, this); Super.isValid(); ++Super)
78*fe6060f1SDimitry Andric     if (RC->contains(*Super))
79*fe6060f1SDimitry Andric       return *Super;
80*fe6060f1SDimitry Andric   return 0;
81*fe6060f1SDimitry Andric }
82*fe6060f1SDimitry Andric 
83*fe6060f1SDimitry Andric const TargetRegisterClass *
84*fe6060f1SDimitry Andric M68kRegisterInfo::getMaximalPhysRegClass(unsigned reg, MVT VT) const {
85*fe6060f1SDimitry Andric   assert(Register::isPhysicalRegister(reg) &&
86*fe6060f1SDimitry Andric          "reg must be a physical register");
87*fe6060f1SDimitry Andric 
88*fe6060f1SDimitry Andric   // Pick the most sub register class of the right type that contains
89*fe6060f1SDimitry Andric   // this physreg.
90*fe6060f1SDimitry Andric   const TargetRegisterClass *BestRC = nullptr;
91*fe6060f1SDimitry Andric   for (regclass_iterator I = regclass_begin(), E = regclass_end(); I != E;
92*fe6060f1SDimitry Andric        ++I) {
93*fe6060f1SDimitry Andric     const TargetRegisterClass *RC = *I;
94*fe6060f1SDimitry Andric     if ((VT == MVT::Other || isTypeLegalForClass(*RC, VT)) &&
95*fe6060f1SDimitry Andric         RC->contains(reg) &&
96*fe6060f1SDimitry Andric         (!BestRC ||
97*fe6060f1SDimitry Andric          (BestRC->hasSubClass(RC) && RC->getNumRegs() > BestRC->getNumRegs())))
98*fe6060f1SDimitry Andric       BestRC = RC;
99*fe6060f1SDimitry Andric   }
100*fe6060f1SDimitry Andric 
101*fe6060f1SDimitry Andric   assert(BestRC && "Couldn't find the register class");
102*fe6060f1SDimitry Andric   return BestRC;
103*fe6060f1SDimitry Andric }
104*fe6060f1SDimitry Andric 
105*fe6060f1SDimitry Andric int M68kRegisterInfo::getRegisterOrder(unsigned Reg,
106*fe6060f1SDimitry Andric                                        const TargetRegisterClass &TRC) const {
107*fe6060f1SDimitry Andric   for (unsigned i = 0; i < TRC.getNumRegs(); ++i) {
108*fe6060f1SDimitry Andric     if (regsOverlap(Reg, TRC.getRegister(i))) {
109*fe6060f1SDimitry Andric       return i;
110*fe6060f1SDimitry Andric     }
111*fe6060f1SDimitry Andric   }
112*fe6060f1SDimitry Andric   return -1;
113*fe6060f1SDimitry Andric }
114*fe6060f1SDimitry Andric 
115*fe6060f1SDimitry Andric int M68kRegisterInfo::getSpillRegisterOrder(unsigned Reg) const {
116*fe6060f1SDimitry Andric   int Result = getRegisterOrder(Reg, *getRegClass(M68k::SPILLRegClassID));
117*fe6060f1SDimitry Andric   assert(Result >= 0 && "Can not determine spill order");
118*fe6060f1SDimitry Andric   return Result;
119*fe6060f1SDimitry Andric }
120*fe6060f1SDimitry Andric 
121*fe6060f1SDimitry Andric BitVector M68kRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
122*fe6060f1SDimitry Andric   const M68kFrameLowering *TFI = getFrameLowering(MF);
123*fe6060f1SDimitry Andric 
124*fe6060f1SDimitry Andric   BitVector Reserved(getNumRegs());
125*fe6060f1SDimitry Andric 
126*fe6060f1SDimitry Andric   // Set a register's and its sub-registers and aliases as reserved.
127*fe6060f1SDimitry Andric   auto setBitVector = [&Reserved, this](unsigned Reg) {
128*fe6060f1SDimitry Andric     for (MCRegAliasIterator I(Reg, this, /* self */ true); I.isValid(); ++I) {
129*fe6060f1SDimitry Andric       Reserved.set(*I);
130*fe6060f1SDimitry Andric     }
131*fe6060f1SDimitry Andric     for (MCSubRegIterator I(Reg, this, /* self */ true); I.isValid(); ++I) {
132*fe6060f1SDimitry Andric       Reserved.set(*I);
133*fe6060f1SDimitry Andric     }
134*fe6060f1SDimitry Andric   };
135*fe6060f1SDimitry Andric 
136*fe6060f1SDimitry Andric   // Registers reserved by users
137*fe6060f1SDimitry Andric   for (size_t Reg = 0, Total = getNumRegs(); Reg != Total; ++Reg) {
138*fe6060f1SDimitry Andric     if (MF.getSubtarget<M68kSubtarget>().isRegisterReservedByUser(Reg))
139*fe6060f1SDimitry Andric       setBitVector(Reg);
140*fe6060f1SDimitry Andric   }
141*fe6060f1SDimitry Andric 
142*fe6060f1SDimitry Andric   setBitVector(M68k::PC);
143*fe6060f1SDimitry Andric   setBitVector(M68k::SP);
144*fe6060f1SDimitry Andric 
145*fe6060f1SDimitry Andric   if (TFI->hasFP(MF)) {
146*fe6060f1SDimitry Andric     setBitVector(FramePtr);
147*fe6060f1SDimitry Andric   }
148*fe6060f1SDimitry Andric 
149*fe6060f1SDimitry Andric   // Set the base-pointer register and its aliases as reserved if needed.
150*fe6060f1SDimitry Andric   if (hasBasePointer(MF)) {
151*fe6060f1SDimitry Andric     CallingConv::ID CC = MF.getFunction().getCallingConv();
152*fe6060f1SDimitry Andric     const uint32_t *RegMask = getCallPreservedMask(MF, CC);
153*fe6060f1SDimitry Andric     if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister()))
154*fe6060f1SDimitry Andric       report_fatal_error("Stack realignment in presence of dynamic allocas is "
155*fe6060f1SDimitry Andric                          "not supported with"
156*fe6060f1SDimitry Andric                          "this calling convention.");
157*fe6060f1SDimitry Andric 
158*fe6060f1SDimitry Andric     setBitVector(getBaseRegister());
159*fe6060f1SDimitry Andric   }
160*fe6060f1SDimitry Andric 
161*fe6060f1SDimitry Andric   return Reserved;
162*fe6060f1SDimitry Andric }
163*fe6060f1SDimitry Andric 
164*fe6060f1SDimitry Andric void M68kRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
165*fe6060f1SDimitry Andric                                            int SPAdj, unsigned FIOperandNum,
166*fe6060f1SDimitry Andric                                            RegScavenger *RS) const {
167*fe6060f1SDimitry Andric   MachineInstr &MI = *II;
168*fe6060f1SDimitry Andric   MachineFunction &MF = *MI.getParent()->getParent();
169*fe6060f1SDimitry Andric   const M68kFrameLowering *TFI = getFrameLowering(MF);
170*fe6060f1SDimitry Andric 
171*fe6060f1SDimitry Andric   // We have either (i,An,Rn) or (i,An) EA form
172*fe6060f1SDimitry Andric   // NOTE Base contains the FI and we need to backtrace a bit to get Disp
173*fe6060f1SDimitry Andric   MachineOperand &Disp = MI.getOperand(FIOperandNum - 1);
174*fe6060f1SDimitry Andric   MachineOperand &Base = MI.getOperand(FIOperandNum);
175*fe6060f1SDimitry Andric 
176*fe6060f1SDimitry Andric   int Imm = (int)(Disp.getImm());
177*fe6060f1SDimitry Andric   int FIndex = (int)(Base.getIndex());
178*fe6060f1SDimitry Andric 
179*fe6060f1SDimitry Andric   // FIXME tail call: implement jmp from mem
180*fe6060f1SDimitry Andric   bool AfterFPPop = false;
181*fe6060f1SDimitry Andric 
182*fe6060f1SDimitry Andric   unsigned BasePtr;
183*fe6060f1SDimitry Andric   if (hasBasePointer(MF))
184*fe6060f1SDimitry Andric     BasePtr = (FIndex < 0 ? FramePtr : getBaseRegister());
185*fe6060f1SDimitry Andric   else if (hasStackRealignment(MF))
186*fe6060f1SDimitry Andric     BasePtr = (FIndex < 0 ? FramePtr : StackPtr);
187*fe6060f1SDimitry Andric   else if (AfterFPPop)
188*fe6060f1SDimitry Andric     BasePtr = StackPtr;
189*fe6060f1SDimitry Andric   else
190*fe6060f1SDimitry Andric     BasePtr = (TFI->hasFP(MF) ? FramePtr : StackPtr);
191*fe6060f1SDimitry Andric 
192*fe6060f1SDimitry Andric   Base.ChangeToRegister(BasePtr, false);
193*fe6060f1SDimitry Andric 
194*fe6060f1SDimitry Andric   // Now add the frame object offset to the offset from FP.
195*fe6060f1SDimitry Andric   int64_t FIOffset;
196*fe6060f1SDimitry Andric   Register IgnoredFrameReg;
197*fe6060f1SDimitry Andric   if (AfterFPPop) {
198*fe6060f1SDimitry Andric     // Tail call jmp happens after FP is popped.
199*fe6060f1SDimitry Andric     const MachineFrameInfo &MFI = MF.getFrameInfo();
200*fe6060f1SDimitry Andric     FIOffset = MFI.getObjectOffset(FIndex) - TFI->getOffsetOfLocalArea();
201*fe6060f1SDimitry Andric   } else {
202*fe6060f1SDimitry Andric     FIOffset =
203*fe6060f1SDimitry Andric         TFI->getFrameIndexReference(MF, FIndex, IgnoredFrameReg).getFixed();
204*fe6060f1SDimitry Andric   }
205*fe6060f1SDimitry Andric 
206*fe6060f1SDimitry Andric   if (BasePtr == StackPtr)
207*fe6060f1SDimitry Andric     FIOffset += SPAdj;
208*fe6060f1SDimitry Andric 
209*fe6060f1SDimitry Andric   Disp.ChangeToImmediate(FIOffset + Imm);
210*fe6060f1SDimitry Andric }
211*fe6060f1SDimitry Andric 
212*fe6060f1SDimitry Andric bool M68kRegisterInfo::requiresRegisterScavenging(
213*fe6060f1SDimitry Andric     const MachineFunction &MF) const {
214*fe6060f1SDimitry Andric   return true;
215*fe6060f1SDimitry Andric }
216*fe6060f1SDimitry Andric 
217*fe6060f1SDimitry Andric bool M68kRegisterInfo::trackLivenessAfterRegAlloc(
218*fe6060f1SDimitry Andric     const MachineFunction &MF) const {
219*fe6060f1SDimitry Andric   return true;
220*fe6060f1SDimitry Andric }
221*fe6060f1SDimitry Andric 
222*fe6060f1SDimitry Andric static bool CantUseSP(const MachineFrameInfo &MFI) {
223*fe6060f1SDimitry Andric   return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment();
224*fe6060f1SDimitry Andric }
225*fe6060f1SDimitry Andric 
226*fe6060f1SDimitry Andric bool M68kRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
227*fe6060f1SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
228*fe6060f1SDimitry Andric 
229*fe6060f1SDimitry Andric   if (!EnableBasePointer)
230*fe6060f1SDimitry Andric     return false;
231*fe6060f1SDimitry Andric 
232*fe6060f1SDimitry Andric   // When we need stack realignment, we can't address the stack from the frame
233*fe6060f1SDimitry Andric   // pointer.  When we have dynamic allocas or stack-adjusting inline asm, we
234*fe6060f1SDimitry Andric   // can't address variables from the stack pointer.  MS inline asm can
235*fe6060f1SDimitry Andric   // reference locals while also adjusting the stack pointer.  When we can't
236*fe6060f1SDimitry Andric   // use both the SP and the FP, we need a separate base pointer register.
237*fe6060f1SDimitry Andric   bool CantUseFP = hasStackRealignment(MF);
238*fe6060f1SDimitry Andric   return CantUseFP && CantUseSP(MFI);
239*fe6060f1SDimitry Andric }
240*fe6060f1SDimitry Andric 
241*fe6060f1SDimitry Andric bool M68kRegisterInfo::canRealignStack(const MachineFunction &MF) const {
242*fe6060f1SDimitry Andric   if (!TargetRegisterInfo::canRealignStack(MF))
243*fe6060f1SDimitry Andric     return false;
244*fe6060f1SDimitry Andric 
245*fe6060f1SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
246*fe6060f1SDimitry Andric   const MachineRegisterInfo *MRI = &MF.getRegInfo();
247*fe6060f1SDimitry Andric 
248*fe6060f1SDimitry Andric   // Stack realignment requires a frame pointer.  If we already started
249*fe6060f1SDimitry Andric   // register allocation with frame pointer elimination, it is too late now.
250*fe6060f1SDimitry Andric   if (!MRI->canReserveReg(FramePtr))
251*fe6060f1SDimitry Andric     return false;
252*fe6060f1SDimitry Andric 
253*fe6060f1SDimitry Andric   // If a base pointer is necessary. Check that it isn't too late to reserve it.
254*fe6060f1SDimitry Andric   if (CantUseSP(MFI))
255*fe6060f1SDimitry Andric     return MRI->canReserveReg(BasePtr);
256*fe6060f1SDimitry Andric 
257*fe6060f1SDimitry Andric   return true;
258*fe6060f1SDimitry Andric }
259*fe6060f1SDimitry Andric 
260*fe6060f1SDimitry Andric Register M68kRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
261*fe6060f1SDimitry Andric   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
262*fe6060f1SDimitry Andric   return TFI->hasFP(MF) ? FramePtr : StackPtr;
263*fe6060f1SDimitry Andric }
264*fe6060f1SDimitry Andric 
265*fe6060f1SDimitry Andric const TargetRegisterClass *M68kRegisterInfo::intRegClass(unsigned size) const {
266*fe6060f1SDimitry Andric   return &M68k::DR32RegClass;
267*fe6060f1SDimitry Andric }
268