LanaiRegisterInfo.cpp revision 327952
1//===-- LanaiRegisterInfo.cpp - Lanai Register Information ------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the Lanai implementation of the TargetRegisterInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "LanaiRegisterInfo.h"
15#include "Lanai.h"
16#include "LanaiSubtarget.h"
17#include "llvm/ADT/BitVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/CodeGen/RegisterScavenging.h"
23#include "llvm/CodeGen/TargetFrameLowering.h"
24#include "llvm/CodeGen/TargetInstrInfo.h"
25#include "llvm/IR/Function.h"
26#include "llvm/IR/Type.h"
27#include "llvm/Support/ErrorHandling.h"
28
29#define GET_REGINFO_TARGET_DESC
30#include "LanaiGenRegisterInfo.inc"
31
32using namespace llvm;
33
34LanaiRegisterInfo::LanaiRegisterInfo() : LanaiGenRegisterInfo(Lanai::RCA) {}
35
36const uint16_t *
37LanaiRegisterInfo::getCalleeSavedRegs(const MachineFunction * /*MF*/) const {
38  return CSR_SaveList;
39}
40
41BitVector LanaiRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
42  BitVector Reserved(getNumRegs());
43
44  Reserved.set(Lanai::R0);
45  Reserved.set(Lanai::R1);
46  Reserved.set(Lanai::PC);
47  Reserved.set(Lanai::R2);
48  Reserved.set(Lanai::SP);
49  Reserved.set(Lanai::R4);
50  Reserved.set(Lanai::FP);
51  Reserved.set(Lanai::R5);
52  Reserved.set(Lanai::RR1);
53  Reserved.set(Lanai::R10);
54  Reserved.set(Lanai::RR2);
55  Reserved.set(Lanai::R11);
56  Reserved.set(Lanai::RCA);
57  Reserved.set(Lanai::R15);
58  if (hasBasePointer(MF))
59    Reserved.set(getBaseRegister());
60  return Reserved;
61}
62
63bool LanaiRegisterInfo::requiresRegisterScavenging(
64    const MachineFunction & /*MF*/) const {
65  return true;
66}
67
68bool LanaiRegisterInfo::trackLivenessAfterRegAlloc(
69    const MachineFunction & /*MF*/) const {
70  return true;
71}
72
73static bool isALUArithLoOpcode(unsigned Opcode) {
74  switch (Opcode) {
75  case Lanai::ADD_I_LO:
76  case Lanai::SUB_I_LO:
77  case Lanai::ADD_F_I_LO:
78  case Lanai::SUB_F_I_LO:
79  case Lanai::ADDC_I_LO:
80  case Lanai::SUBB_I_LO:
81  case Lanai::ADDC_F_I_LO:
82  case Lanai::SUBB_F_I_LO:
83    return true;
84  default:
85    return false;
86  }
87}
88
89static unsigned getOppositeALULoOpcode(unsigned Opcode) {
90  switch (Opcode) {
91  case Lanai::ADD_I_LO:
92    return Lanai::SUB_I_LO;
93  case Lanai::SUB_I_LO:
94    return Lanai::ADD_I_LO;
95  case Lanai::ADD_F_I_LO:
96    return Lanai::SUB_F_I_LO;
97  case Lanai::SUB_F_I_LO:
98    return Lanai::ADD_F_I_LO;
99  case Lanai::ADDC_I_LO:
100    return Lanai::SUBB_I_LO;
101  case Lanai::SUBB_I_LO:
102    return Lanai::ADDC_I_LO;
103  case Lanai::ADDC_F_I_LO:
104    return Lanai::SUBB_F_I_LO;
105  case Lanai::SUBB_F_I_LO:
106    return Lanai::ADDC_F_I_LO;
107  default:
108    llvm_unreachable("Invalid ALU lo opcode");
109  }
110}
111
112static unsigned getRRMOpcodeVariant(unsigned Opcode) {
113  switch (Opcode) {
114  case Lanai::LDBs_RI:
115    return Lanai::LDBs_RR;
116  case Lanai::LDBz_RI:
117    return Lanai::LDBz_RR;
118  case Lanai::LDHs_RI:
119    return Lanai::LDHs_RR;
120  case Lanai::LDHz_RI:
121    return Lanai::LDHz_RR;
122  case Lanai::LDW_RI:
123    return Lanai::LDW_RR;
124  case Lanai::STB_RI:
125    return Lanai::STB_RR;
126  case Lanai::STH_RI:
127    return Lanai::STH_RR;
128  case Lanai::SW_RI:
129    return Lanai::SW_RR;
130  default:
131    llvm_unreachable("Opcode has no RRM variant");
132  }
133}
134
135void LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
136                                            int SPAdj, unsigned FIOperandNum,
137                                            RegScavenger *RS) const {
138  assert(SPAdj == 0 && "Unexpected");
139
140  MachineInstr &MI = *II;
141  MachineFunction &MF = *MI.getParent()->getParent();
142  const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
143  const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
144  bool HasFP = TFI->hasFP(MF);
145  DebugLoc DL = MI.getDebugLoc();
146
147  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
148
149  int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) +
150               MI.getOperand(FIOperandNum + 1).getImm();
151
152  // Addressable stack objects are addressed using neg. offsets from fp
153  // or pos. offsets from sp/basepointer
154  if (!HasFP || (needsStackRealignment(MF) && FrameIndex >= 0))
155    Offset += MF.getFrameInfo().getStackSize();
156
157  unsigned FrameReg = getFrameRegister(MF);
158  if (FrameIndex >= 0) {
159    if (hasBasePointer(MF))
160      FrameReg = getBaseRegister();
161    else if (needsStackRealignment(MF))
162      FrameReg = Lanai::SP;
163  }
164
165  // Replace frame index with a frame pointer reference.
166  // If the offset is small enough to fit in the immediate field, directly
167  // encode it.
168  // Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence.
169  if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) ||
170      !isInt<16>(Offset)) {
171    assert(RS && "Register scavenging must be on");
172    unsigned Reg = RS->FindUnusedReg(&Lanai::GPRRegClass);
173    if (!Reg)
174      Reg = RS->scavengeRegister(&Lanai::GPRRegClass, II, SPAdj);
175    assert(Reg && "Register scavenger failed");
176
177    bool HasNegOffset = false;
178    // ALU ops have unsigned immediate values. If the Offset is negative, we
179    // negate it here and reverse the opcode later.
180    if (Offset < 0) {
181      HasNegOffset = true;
182      Offset = -Offset;
183    }
184
185    if (!isInt<16>(Offset)) {
186      // Reg = hi(offset) | lo(offset)
187      BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg)
188          .addImm(static_cast<uint32_t>(Offset) >> 16);
189      BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg)
190          .addReg(Reg)
191          .addImm(Offset & 0xffffU);
192    } else {
193      // Reg = mov(offset)
194      BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg)
195          .addImm(0)
196          .addImm(Offset);
197    }
198    // Reg = FrameReg OP Reg
199    if (MI.getOpcode() == Lanai::ADD_I_LO) {
200      BuildMI(*MI.getParent(), II, DL,
201              HasNegOffset ? TII->get(Lanai::SUB_R) : TII->get(Lanai::ADD_R),
202              MI.getOperand(0).getReg())
203          .addReg(FrameReg)
204          .addReg(Reg)
205          .addImm(LPCC::ICC_T);
206      MI.eraseFromParent();
207      return;
208    }
209    if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) {
210      MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode())));
211      if (HasNegOffset) {
212        // Change the ALU op (operand 3) from LPAC::ADD (the default) to
213        // LPAC::SUB with the already negated offset.
214        assert((MI.getOperand(3).getImm() == LPAC::ADD) &&
215               "Unexpected ALU op in RRM instruction");
216        MI.getOperand(3).setImm(LPAC::SUB);
217      }
218    } else
219      llvm_unreachable("Unexpected opcode in frame index operation");
220
221    MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
222    MI.getOperand(FIOperandNum + 1)
223        .ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false,
224                          /*isKill=*/true);
225    return;
226  }
227
228  // ALU arithmetic ops take unsigned immediates. If the offset is negative,
229  // we replace the instruction with one that inverts the opcode and negates
230  // the immediate.
231  if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) {
232    unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode());
233    // We know this is an ALU op, so we know the operands are as follows:
234    // 0: destination register
235    // 1: source register (frame register)
236    // 2: immediate
237    BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode),
238            MI.getOperand(0).getReg())
239        .addReg(FrameReg)
240        .addImm(-Offset);
241    MI.eraseFromParent();
242  } else {
243    MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
244    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
245  }
246}
247
248bool LanaiRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
249  const MachineFrameInfo &MFI = MF.getFrameInfo();
250  // When we need stack realignment and there are dynamic allocas, we can't
251  // reference off of the stack pointer, so we reserve a base pointer.
252  if (needsStackRealignment(MF) && MFI.hasVarSizedObjects())
253    return true;
254
255  return false;
256}
257
258unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; }
259
260unsigned
261LanaiRegisterInfo::getFrameRegister(const MachineFunction & /*MF*/) const {
262  return Lanai::FP;
263}
264
265unsigned LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; }
266
267const uint32_t *
268LanaiRegisterInfo::getCallPreservedMask(const MachineFunction & /*MF*/,
269                                        CallingConv::ID /*CC*/) const {
270  return CSR_RegMask;
271}
272