1//===-- HexagonRegisterInfo.cpp - Hexagon Register Information ------------===//
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 Hexagon implementation of the TargetRegisterInfo
11// class.
12//
13//===----------------------------------------------------------------------===//
14
15#include "HexagonRegisterInfo.h"
16#include "Hexagon.h"
17#include "HexagonSubtarget.h"
18#include "HexagonTargetMachine.h"
19#include "HexagonMachineFunctionInfo.h"
20#include "llvm/Function.h"
21#include "llvm/Type.h"
22#include "llvm/ADT/BitVector.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
25#include "llvm/CodeGen/MachineFunction.h"
26#include "llvm/CodeGen/MachineFunctionPass.h"
27#include "llvm/CodeGen/MachineFrameInfo.h"
28#include "llvm/CodeGen/MachineRegisterInfo.h"
29#include "llvm/CodeGen/RegisterScavenging.h"
30#include "llvm/MC/MachineLocation.h"
31#include "llvm/Target/TargetInstrInfo.h"
32#include "llvm/Target/TargetMachine.h"
33#include "llvm/Target/TargetOptions.h"
34#include "llvm/Support/CommandLine.h"
35#include "llvm/Support/ErrorHandling.h"
36
37using namespace llvm;
38
39
40HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st,
41                                     const HexagonInstrInfo &tii)
42  : HexagonGenRegisterInfo(Hexagon::R31),
43    Subtarget(st),
44   TII(tii) {
45}
46
47const uint16_t* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction
48                                                        *MF)
49  const {
50  static const uint16_t CalleeSavedRegsV2[] = {
51    Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
52  };
53  static const uint16_t CalleeSavedRegsV3[] = {
54    Hexagon::R16,   Hexagon::R17,   Hexagon::R18,   Hexagon::R19,
55    Hexagon::R20,   Hexagon::R21,   Hexagon::R22,   Hexagon::R23,
56    Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
57  };
58
59  switch(Subtarget.getHexagonArchVersion()) {
60  case HexagonSubtarget::V1:
61    break;
62  case HexagonSubtarget::V2:
63    return CalleeSavedRegsV2;
64  case HexagonSubtarget::V3:
65  case HexagonSubtarget::V4:
66  case HexagonSubtarget::V5:
67    return CalleeSavedRegsV3;
68  }
69  llvm_unreachable("Callee saved registers requested for unknown architecture "
70                   "version");
71}
72
73BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
74  const {
75  BitVector Reserved(getNumRegs());
76  Reserved.set(HEXAGON_RESERVED_REG_1);
77  Reserved.set(HEXAGON_RESERVED_REG_2);
78  Reserved.set(Hexagon::R29);
79  Reserved.set(Hexagon::R30);
80  Reserved.set(Hexagon::R31);
81  Reserved.set(Hexagon::D14);
82  Reserved.set(Hexagon::D15);
83  Reserved.set(Hexagon::LC0);
84  Reserved.set(Hexagon::LC1);
85  Reserved.set(Hexagon::SA0);
86  Reserved.set(Hexagon::SA1);
87  return Reserved;
88}
89
90
91const TargetRegisterClass* const*
92HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
93  static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = {
94    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
95    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
96    };
97  static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = {
98    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
99    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
100    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
101    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
102    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
103    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
104  };
105
106  switch(Subtarget.getHexagonArchVersion()) {
107  case HexagonSubtarget::V1:
108    break;
109  case HexagonSubtarget::V2:
110    return CalleeSavedRegClassesV2;
111  case HexagonSubtarget::V3:
112  case HexagonSubtarget::V4:
113  case HexagonSubtarget::V5:
114    return CalleeSavedRegClassesV3;
115  }
116  llvm_unreachable("Callee saved register classes requested for unknown "
117                   "architecture version");
118}
119
120void HexagonRegisterInfo::
121eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
122                              MachineBasicBlock::iterator I) const {
123  MachineInstr &MI = *I;
124
125  if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) {
126    // Hexagon_TODO: add code
127  } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) {
128    // Hexagon_TODO: add code
129  } else {
130    llvm_unreachable("Cannot handle this call frame pseudo instruction");
131  }
132  MBB.erase(I);
133}
134
135void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
136                                            int SPAdj, RegScavenger *RS) const {
137
138  //
139  // Hexagon_TODO: Do we need to enforce this for Hexagon?
140  assert(SPAdj == 0 && "Unexpected");
141
142
143  unsigned i = 0;
144  MachineInstr &MI = *II;
145  while (!MI.getOperand(i).isFI()) {
146    ++i;
147    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
148  }
149
150  int FrameIndex = MI.getOperand(i).getIndex();
151
152  // Addressable stack objects are accessed using neg. offsets from %fp.
153  MachineFunction &MF = *MI.getParent()->getParent();
154  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
155  MachineFrameInfo &MFI = *MF.getFrameInfo();
156
157  unsigned FrameReg = getFrameRegister(MF);
158  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
159  if (!TFI->hasFP(MF)) {
160    // We will not reserve space on the stack for the lr and fp registers.
161    Offset -= 2 * Hexagon_WordSize;
162  }
163
164  const unsigned FrameSize = MFI.getStackSize();
165
166  if (!MFI.hasVarSizedObjects() &&
167      TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
168      !TII.isSpillPredRegOp(&MI)) {
169    // Replace frame index with a stack pointer reference.
170    MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true);
171    MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
172  } else {
173    // Replace frame index with a frame pointer reference.
174    if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
175
176      // If the offset overflows, then correct it.
177      //
178      // For loads, we do not need a reserved register
179      // r0 = memw(r30 + #10000) to:
180      //
181      // r0 = add(r30, #10000)
182      // r0 = memw(r0)
183      if ( (MI.getOpcode() == Hexagon::LDriw)  ||
184           (MI.getOpcode() == Hexagon::LDrid)   ||
185           (MI.getOpcode() == Hexagon::LDrih)   ||
186           (MI.getOpcode() == Hexagon::LDriuh)  ||
187           (MI.getOpcode() == Hexagon::LDrib)   ||
188           (MI.getOpcode() == Hexagon::LDriub)  ||
189           (MI.getOpcode() == Hexagon::LDriw_f) ||
190           (MI.getOpcode() == Hexagon::LDrid_f)) {
191        unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
192          getSubReg(MI.getOperand(0).getReg(), Hexagon::subreg_loreg) :
193          MI.getOperand(0).getReg();
194
195        // Check if offset can fit in addi.
196        if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
197          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
198                  TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
199          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
200                  TII.get(Hexagon::ADD_rr),
201                  dstReg).addReg(FrameReg).addReg(dstReg);
202        } else {
203          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
204                  TII.get(Hexagon::ADD_ri),
205                  dstReg).addReg(FrameReg).addImm(Offset);
206        }
207
208        MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
209        MI.getOperand(i+1).ChangeToImmediate(0);
210      } else if ((MI.getOpcode() == Hexagon::STriw_indexed) ||
211                 (MI.getOpcode() == Hexagon::STriw) ||
212                 (MI.getOpcode() == Hexagon::STrid) ||
213                 (MI.getOpcode() == Hexagon::STrih) ||
214                 (MI.getOpcode() == Hexagon::STrib) ||
215                 (MI.getOpcode() == Hexagon::STrid_f) ||
216                 (MI.getOpcode() == Hexagon::STriw_f)) {
217        // For stores, we need a reserved register. Change
218        // memw(r30 + #10000) = r0 to:
219        //
220        // rs = add(r30, #10000);
221        // memw(rs) = r0
222        unsigned resReg = HEXAGON_RESERVED_REG_1;
223
224        // Check if offset can fit in addi.
225        if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
226          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
227                  TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
228          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
229                  TII.get(Hexagon::ADD_rr),
230                  resReg).addReg(FrameReg).addReg(resReg);
231        } else {
232          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
233                  TII.get(Hexagon::ADD_ri),
234                  resReg).addReg(FrameReg).addImm(Offset);
235        }
236        MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
237        MI.getOperand(i+1).ChangeToImmediate(0);
238      } else if (TII.isMemOp(&MI)) {
239        unsigned resReg = HEXAGON_RESERVED_REG_1;
240        if (!MFI.hasVarSizedObjects() &&
241            TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
242          MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false,
243                                            true);
244          MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
245        } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
246          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
247                  TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
248          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
249                  TII.get(Hexagon::ADD_rr),
250                  resReg).addReg(FrameReg).addReg(resReg);
251          MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
252          MI.getOperand(i+1).ChangeToImmediate(0);
253        } else {
254          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
255                  TII.get(Hexagon::ADD_ri),
256                  resReg).addReg(FrameReg).addImm(Offset);
257          MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
258          MI.getOperand(i+1).ChangeToImmediate(0);
259        }
260      } else {
261        unsigned dstReg = MI.getOperand(0).getReg();
262        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
263                TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
264        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
265                TII.get(Hexagon::ADD_rr),
266                dstReg).addReg(FrameReg).addReg(dstReg);
267        // Can we delete MI??? r2 = add (r2, #0).
268        MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
269        MI.getOperand(i+1).ChangeToImmediate(0);
270      }
271    } else {
272      // If the offset is small enough to fit in the immediate field, directly
273      // encode it.
274      MI.getOperand(i).ChangeToRegister(FrameReg, false);
275      MI.getOperand(i+1).ChangeToImmediate(Offset);
276    }
277  }
278
279}
280
281unsigned HexagonRegisterInfo::getRARegister() const {
282  return Hexagon::R31;
283}
284
285unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
286                                               &MF) const {
287  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
288  if (TFI->hasFP(MF)) {
289    return Hexagon::R30;
290  }
291
292  return Hexagon::R29;
293}
294
295unsigned HexagonRegisterInfo::getFrameRegister() const {
296  return Hexagon::R30;
297}
298
299unsigned HexagonRegisterInfo::getStackRegister() const {
300  return Hexagon::R29;
301}
302
303void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove>
304                                               &Moves)  const
305{
306  // VirtualFP = (R30 + #0).
307  unsigned FPReg = getFrameRegister();
308  MachineLocation Dst(MachineLocation::VirtualFP);
309  MachineLocation Src(FPReg, 0);
310  Moves.push_back(MachineMove(0, Dst, Src));
311}
312
313// Get the weight in units of pressure for this register class.
314const RegClassWeight &
315HexagonRegisterInfo::getRegClassWeight(const TargetRegisterClass *RC) const {
316  // Each TargetRegisterClass has a per register weight, and weight
317  // limit which must be less than the limits of its pressure sets.
318  static const RegClassWeight RCWeightTable[] = {
319    {1, 32}, // IntRegs
320    {1, 8},  // CRRegs
321    {1, 4},  // PredRegs
322    {2, 16}, // DoubleRegs
323    {0, 0} };
324  return RCWeightTable[RC->getID()];
325}
326
327/// Get the number of dimensions of register pressure.
328unsigned HexagonRegisterInfo::getNumRegPressureSets() const {
329  return 4;
330}
331
332/// Get the name of this register unit pressure set.
333const char *HexagonRegisterInfo::getRegPressureSetName(unsigned Idx) const {
334  static const char *const RegPressureSetName[] = {
335    "IntRegsRegSet",
336    "CRRegsRegSet",
337    "PredRegsRegSet",
338    "DoubleRegsRegSet"
339  };
340  assert((Idx < 4) && "Index out of bounds");
341  return RegPressureSetName[Idx];
342}
343
344/// Get the register unit pressure limit for this dimension.
345/// This limit must be adjusted dynamically for reserved registers.
346unsigned HexagonRegisterInfo::getRegPressureSetLimit(unsigned Idx) const {
347  static const int RegPressureLimit [] = { 16, 4, 2, 8 };
348  assert((Idx < 4) && "Index out of bounds");
349  return RegPressureLimit[Idx];
350}
351
352const int*
353HexagonRegisterInfo::getRegClassPressureSets(const TargetRegisterClass *RC)
354  const {
355  static const int RCSetsTable[] = {
356    0,  -1,  // IntRegs
357    1,  -1,  // CRRegs
358    2,  -1,  // PredRegs
359    0,  -1,  // DoubleRegs
360    -1 };
361  static const unsigned RCSetStartTable[] = { 0, 2, 4, 6, 0 };
362  unsigned SetListStart = RCSetStartTable[RC->getID()];
363  return &RCSetsTable[SetListStart];
364}
365unsigned HexagonRegisterInfo::getEHExceptionRegister() const {
366  llvm_unreachable("What is the exception register");
367}
368
369unsigned HexagonRegisterInfo::getEHHandlerRegister() const {
370  llvm_unreachable("What is the exception handler register");
371}
372
373#define GET_REGINFO_TARGET_DESC
374#include "HexagonGenRegisterInfo.inc"
375