1234353Sdim//===-- XCoreRegisterInfo.cpp - XCore Register Information ----------------===//
2193323Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193323Sed//
7193323Sed//===----------------------------------------------------------------------===//
8193323Sed//
9193323Sed// This file contains the XCore implementation of the MRegisterInfo class.
10193323Sed//
11193323Sed//===----------------------------------------------------------------------===//
12193323Sed
13193323Sed#include "XCoreRegisterInfo.h"
14249423Sdim#include "XCore.h"
15276479Sdim#include "XCoreInstrInfo.h"
16193323Sed#include "XCoreMachineFunctionInfo.h"
17280031Sdim#include "XCoreSubtarget.h"
18249423Sdim#include "llvm/ADT/BitVector.h"
19249423Sdim#include "llvm/ADT/STLExtras.h"
20249423Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
21249423Sdim#include "llvm/CodeGen/MachineFunction.h"
22193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h"
23193323Sed#include "llvm/CodeGen/MachineModuleInfo.h"
24193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h"
25193323Sed#include "llvm/CodeGen/RegisterScavenging.h"
26249423Sdim#include "llvm/IR/Function.h"
27249423Sdim#include "llvm/IR/Type.h"
28249423Sdim#include "llvm/Support/Debug.h"
29249423Sdim#include "llvm/Support/ErrorHandling.h"
30276479Sdim#include "llvm/Support/MathExtras.h"
31249423Sdim#include "llvm/Support/raw_ostream.h"
32327952Sdim#include "llvm/CodeGen/TargetFrameLowering.h"
33193323Sed#include "llvm/Target/TargetMachine.h"
34193323Sed#include "llvm/Target/TargetOptions.h"
35193323Sed
36276479Sdimusing namespace llvm;
37276479Sdim
38276479Sdim#define DEBUG_TYPE "xcore-reg-info"
39276479Sdim
40224145Sdim#define GET_REGINFO_TARGET_DESC
41224145Sdim#include "XCoreGenRegisterInfo.inc"
42224145Sdim
43261991SdimXCoreRegisterInfo::XCoreRegisterInfo()
44261991Sdim  : XCoreGenRegisterInfo(XCore::LR) {
45193323Sed}
46193323Sed
47193323Sed// helper functions
48193323Sedstatic inline bool isImmUs(unsigned val) {
49193323Sed  return val <= 11;
50193323Sed}
51193323Sed
52193323Sedstatic inline bool isImmU6(unsigned val) {
53193323Sed  return val < (1 << 6);
54193323Sed}
55193323Sed
56193323Sedstatic inline bool isImmU16(unsigned val) {
57193323Sed  return val < (1 << 16);
58193323Sed}
59193323Sed
60276479Sdim
61276479Sdimstatic void InsertFPImmInst(MachineBasicBlock::iterator II,
62276479Sdim                            const XCoreInstrInfo &TII,
63276479Sdim                            unsigned Reg, unsigned FrameReg, int Offset ) {
64276479Sdim  MachineInstr &MI = *II;
65276479Sdim  MachineBasicBlock &MBB = *MI.getParent();
66276479Sdim  DebugLoc dl = MI.getDebugLoc();
67276479Sdim
68276479Sdim  switch (MI.getOpcode()) {
69276479Sdim  case XCore::LDWFI:
70276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
71276479Sdim          .addReg(FrameReg)
72276479Sdim          .addImm(Offset)
73276479Sdim          .addMemOperand(*MI.memoperands_begin());
74276479Sdim    break;
75276479Sdim  case XCore::STWFI:
76276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
77276479Sdim          .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
78276479Sdim          .addReg(FrameReg)
79276479Sdim          .addImm(Offset)
80276479Sdim          .addMemOperand(*MI.memoperands_begin());
81276479Sdim    break;
82276479Sdim  case XCore::LDAWFI:
83276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
84276479Sdim          .addReg(FrameReg)
85276479Sdim          .addImm(Offset);
86276479Sdim    break;
87276479Sdim  default:
88276479Sdim    llvm_unreachable("Unexpected Opcode");
89276479Sdim  }
90276479Sdim}
91276479Sdim
92276479Sdimstatic void InsertFPConstInst(MachineBasicBlock::iterator II,
93276479Sdim                              const XCoreInstrInfo &TII,
94276479Sdim                              unsigned Reg, unsigned FrameReg,
95276479Sdim                              int Offset, RegScavenger *RS ) {
96276479Sdim  assert(RS && "requiresRegisterScavenging failed");
97276479Sdim  MachineInstr &MI = *II;
98276479Sdim  MachineBasicBlock &MBB = *MI.getParent();
99276479Sdim  DebugLoc dl = MI.getDebugLoc();
100276479Sdim  unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
101280031Sdim  RS->setRegUsed(ScratchOffset);
102276479Sdim  TII.loadImmediate(MBB, II, ScratchOffset, Offset);
103276479Sdim
104276479Sdim  switch (MI.getOpcode()) {
105276479Sdim  case XCore::LDWFI:
106276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
107276479Sdim          .addReg(FrameReg)
108276479Sdim          .addReg(ScratchOffset, RegState::Kill)
109276479Sdim          .addMemOperand(*MI.memoperands_begin());
110276479Sdim    break;
111276479Sdim  case XCore::STWFI:
112276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
113276479Sdim          .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
114276479Sdim          .addReg(FrameReg)
115276479Sdim          .addReg(ScratchOffset, RegState::Kill)
116276479Sdim          .addMemOperand(*MI.memoperands_begin());
117276479Sdim    break;
118276479Sdim  case XCore::LDAWFI:
119276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
120276479Sdim          .addReg(FrameReg)
121276479Sdim          .addReg(ScratchOffset, RegState::Kill);
122276479Sdim    break;
123276479Sdim  default:
124276479Sdim    llvm_unreachable("Unexpected Opcode");
125276479Sdim  }
126276479Sdim}
127276479Sdim
128276479Sdimstatic void InsertSPImmInst(MachineBasicBlock::iterator II,
129276479Sdim                            const XCoreInstrInfo &TII,
130276479Sdim                            unsigned Reg, int Offset) {
131276479Sdim  MachineInstr &MI = *II;
132276479Sdim  MachineBasicBlock &MBB = *MI.getParent();
133276479Sdim  DebugLoc dl = MI.getDebugLoc();
134276479Sdim  bool isU6 = isImmU6(Offset);
135276479Sdim
136276479Sdim  switch (MI.getOpcode()) {
137276479Sdim  int NewOpcode;
138276479Sdim  case XCore::LDWFI:
139276479Sdim    NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
140276479Sdim    BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
141276479Sdim          .addImm(Offset)
142276479Sdim          .addMemOperand(*MI.memoperands_begin());
143276479Sdim    break;
144276479Sdim  case XCore::STWFI:
145276479Sdim    NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
146276479Sdim    BuildMI(MBB, II, dl, TII.get(NewOpcode))
147276479Sdim          .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
148276479Sdim          .addImm(Offset)
149276479Sdim          .addMemOperand(*MI.memoperands_begin());
150276479Sdim    break;
151276479Sdim  case XCore::LDAWFI:
152276479Sdim    NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
153276479Sdim    BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
154276479Sdim          .addImm(Offset);
155276479Sdim    break;
156276479Sdim  default:
157276479Sdim    llvm_unreachable("Unexpected Opcode");
158276479Sdim  }
159276479Sdim}
160276479Sdim
161276479Sdimstatic void InsertSPConstInst(MachineBasicBlock::iterator II,
162276479Sdim                                const XCoreInstrInfo &TII,
163276479Sdim                                unsigned Reg, int Offset, RegScavenger *RS ) {
164276479Sdim  assert(RS && "requiresRegisterScavenging failed");
165276479Sdim  MachineInstr &MI = *II;
166276479Sdim  MachineBasicBlock &MBB = *MI.getParent();
167276479Sdim  DebugLoc dl = MI.getDebugLoc();
168276479Sdim  unsigned OpCode = MI.getOpcode();
169276479Sdim
170276479Sdim  unsigned ScratchBase;
171276479Sdim  if (OpCode==XCore::STWFI) {
172276479Sdim    ScratchBase = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
173280031Sdim    RS->setRegUsed(ScratchBase);
174276479Sdim  } else
175276479Sdim    ScratchBase = Reg;
176276479Sdim  BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0);
177276479Sdim  unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
178280031Sdim  RS->setRegUsed(ScratchOffset);
179276479Sdim  TII.loadImmediate(MBB, II, ScratchOffset, Offset);
180276479Sdim
181276479Sdim  switch (OpCode) {
182276479Sdim  case XCore::LDWFI:
183276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
184276479Sdim          .addReg(ScratchBase, RegState::Kill)
185276479Sdim          .addReg(ScratchOffset, RegState::Kill)
186276479Sdim          .addMemOperand(*MI.memoperands_begin());
187276479Sdim    break;
188276479Sdim  case XCore::STWFI:
189276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
190276479Sdim          .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
191276479Sdim          .addReg(ScratchBase, RegState::Kill)
192276479Sdim          .addReg(ScratchOffset, RegState::Kill)
193276479Sdim          .addMemOperand(*MI.memoperands_begin());
194276479Sdim    break;
195276479Sdim  case XCore::LDAWFI:
196276479Sdim    BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
197276479Sdim          .addReg(ScratchBase, RegState::Kill)
198276479Sdim          .addReg(ScratchOffset, RegState::Kill);
199276479Sdim    break;
200276479Sdim  default:
201276479Sdim    llvm_unreachable("Unexpected Opcode");
202276479Sdim  }
203276479Sdim}
204276479Sdim
205206274Srdivackybool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
206360784Sdim  return MF.needsFrameMoves();
207193323Sed}
208193323Sed
209288943Sdimconst MCPhysReg *
210288943SdimXCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
211276479Sdim  // The callee saved registers LR & FP are explicitly handled during
212276479Sdim  // emitPrologue & emitEpilogue and related functions.
213276479Sdim  static const MCPhysReg CalleeSavedRegs[] = {
214193323Sed    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
215276479Sdim    XCore::R8, XCore::R9, XCore::R10,
216193323Sed    0
217193323Sed  };
218276479Sdim  static const MCPhysReg CalleeSavedRegsFP[] = {
219276479Sdim    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
220276479Sdim    XCore::R8, XCore::R9,
221276479Sdim    0
222276479Sdim  };
223288943Sdim  const XCoreFrameLowering *TFI = getFrameLowering(*MF);
224276479Sdim  if (TFI->hasFP(*MF))
225276479Sdim    return CalleeSavedRegsFP;
226193323Sed  return CalleeSavedRegs;
227193323Sed}
228193323Sed
229193323SedBitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
230193323Sed  BitVector Reserved(getNumRegs());
231288943Sdim  const XCoreFrameLowering *TFI = getFrameLowering(MF);
232218893Sdim
233193323Sed  Reserved.set(XCore::CP);
234193323Sed  Reserved.set(XCore::DP);
235193323Sed  Reserved.set(XCore::SP);
236193323Sed  Reserved.set(XCore::LR);
237218893Sdim  if (TFI->hasFP(MF)) {
238193323Sed    Reserved.set(XCore::R10);
239193323Sed  }
240193323Sed  return Reserved;
241193323Sed}
242193323Sed
243193323Sedbool
244193323SedXCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
245276479Sdim  return true;
246193323Sed}
247193323Sed
248221345Sdimbool
249239462SdimXCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
250276479Sdim  return true;
251239462Sdim}
252239462Sdim
253239462Sdimbool
254221345SdimXCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
255221345Sdim  return false;
256221345Sdim}
257221345Sdim
258212904Sdimvoid
259198090SrdivackyXCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
260249423Sdim                                       int SPAdj, unsigned FIOperandNum,
261249423Sdim                                       RegScavenger *RS) const {
262193323Sed  assert(SPAdj == 0 && "Unexpected");
263193323Sed  MachineInstr &MI = *II;
264249423Sdim  MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
265193323Sed  int FrameIndex = FrameOp.getIndex();
266193323Sed
267193323Sed  MachineFunction &MF = *MI.getParent()->getParent();
268276479Sdim  const XCoreInstrInfo &TII =
269280031Sdim      *static_cast<const XCoreInstrInfo *>(MF.getSubtarget().getInstrInfo());
270276479Sdim
271288943Sdim  const XCoreFrameLowering *TFI = getFrameLowering(MF);
272314564Sdim  int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);
273314564Sdim  int StackSize = MF.getFrameInfo().getStackSize();
274193323Sed
275193323Sed  #ifndef NDEBUG
276341825Sdim  LLVM_DEBUG(errs() << "\nFunction         : " << MF.getName() << "\n");
277341825Sdim  LLVM_DEBUG(errs() << "<--------->\n");
278341825Sdim  LLVM_DEBUG(MI.print(errs()));
279341825Sdim  LLVM_DEBUG(errs() << "FrameIndex         : " << FrameIndex << "\n");
280341825Sdim  LLVM_DEBUG(errs() << "FrameOffset        : " << Offset << "\n");
281341825Sdim  LLVM_DEBUG(errs() << "StackSize          : " << StackSize << "\n");
282341825Sdim#endif
283193323Sed
284193323Sed  Offset += StackSize;
285224145Sdim
286353358Sdim  Register FrameReg = getFrameRegister(MF);
287224145Sdim
288224145Sdim  // Special handling of DBG_VALUE instructions.
289224145Sdim  if (MI.isDebugValue()) {
290249423Sdim    MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
291249423Sdim    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
292224145Sdim    return;
293224145Sdim  }
294224145Sdim
295193323Sed  // fold constant into offset.
296249423Sdim  Offset += MI.getOperand(FIOperandNum + 1).getImm();
297249423Sdim  MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
298341825Sdim
299193323Sed  assert(Offset%4 == 0 && "Misaligned stack offset");
300341825Sdim  LLVM_DEBUG(errs() << "Offset             : " << Offset << "\n"
301341825Sdim                    << "<--------->\n");
302193323Sed  Offset/=4;
303341825Sdim
304360784Sdim  Register Reg = MI.getOperand(0).getReg();
305276479Sdim  assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
306193323Sed
307276479Sdim  if (TFI->hasFP(MF)) {
308276479Sdim    if (isImmUs(Offset))
309276479Sdim      InsertFPImmInst(II, TII, Reg, FrameReg, Offset);
310276479Sdim    else
311276479Sdim      InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS);
312193323Sed  } else {
313276479Sdim    if (isImmU16(Offset))
314276479Sdim      InsertSPImmInst(II, TII, Reg, Offset);
315276479Sdim    else
316276479Sdim      InsertSPConstInst(II, TII, Reg, Offset, RS);
317193323Sed  }
318193323Sed  // Erase old instruction.
319276479Sdim  MachineBasicBlock &MBB = *MI.getParent();
320193323Sed  MBB.erase(II);
321193323Sed}
322193323Sed
323193323Sed
324353358SdimRegister XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
325288943Sdim  const XCoreFrameLowering *TFI = getFrameLowering(MF);
326218893Sdim
327218893Sdim  return TFI->hasFP(MF) ? XCore::R10 : XCore::SP;
328193323Sed}
329