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 "HexagonMachineFunctionInfo.h"
18#include "HexagonSubtarget.h"
19#include "HexagonTargetMachine.h"
20#include "llvm/ADT/BitVector.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/CodeGen/MachineFrameInfo.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineFunctionPass.h"
25#include "llvm/CodeGen/MachineInstrBuilder.h"
26#include "llvm/CodeGen/MachineRegisterInfo.h"
27#include "llvm/CodeGen/RegisterScavenging.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/Type.h"
30#include "llvm/MC/MachineLocation.h"
31#include "llvm/Support/CommandLine.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Target/TargetInstrInfo.h"
34#include "llvm/Target/TargetMachine.h"
35#include "llvm/Target/TargetOptions.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::eliminateFrameIndex(MachineBasicBlock::iterator II,
121                                              int SPAdj, unsigned FIOperandNum,
122                                              RegScavenger *RS) const {
123  //
124  // Hexagon_TODO: Do we need to enforce this for Hexagon?
125  assert(SPAdj == 0 && "Unexpected");
126
127  MachineInstr &MI = *II;
128  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
129
130  // Addressable stack objects are accessed using neg. offsets from %fp.
131  MachineFunction &MF = *MI.getParent()->getParent();
132  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
133  MachineFrameInfo &MFI = *MF.getFrameInfo();
134
135  unsigned FrameReg = getFrameRegister(MF);
136  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
137  if (!TFI->hasFP(MF)) {
138    // We will not reserve space on the stack for the lr and fp registers.
139    Offset -= 2 * Hexagon_WordSize;
140  }
141
142  const unsigned FrameSize = MFI.getStackSize();
143
144  if (!MFI.hasVarSizedObjects() &&
145      TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
146      !TII.isSpillPredRegOp(&MI)) {
147    // Replace frame index with a stack pointer reference.
148    MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), false,
149                                                 false, true);
150    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(FrameSize+Offset);
151  } else {
152    // Replace frame index with a frame pointer reference.
153    if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
154
155      // If the offset overflows, then correct it.
156      //
157      // For loads, we do not need a reserved register
158      // r0 = memw(r30 + #10000) to:
159      //
160      // r0 = add(r30, #10000)
161      // r0 = memw(r0)
162      if ( (MI.getOpcode() == Hexagon::LDriw)  ||
163           (MI.getOpcode() == Hexagon::LDrid)   ||
164           (MI.getOpcode() == Hexagon::LDrih)   ||
165           (MI.getOpcode() == Hexagon::LDriuh)  ||
166           (MI.getOpcode() == Hexagon::LDrib)   ||
167           (MI.getOpcode() == Hexagon::LDriub)  ||
168           (MI.getOpcode() == Hexagon::LDriw_f) ||
169           (MI.getOpcode() == Hexagon::LDrid_f)) {
170        unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
171          getSubReg(MI.getOperand(0).getReg(), Hexagon::subreg_loreg) :
172          MI.getOperand(0).getReg();
173
174        // Check if offset can fit in addi.
175        if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
176          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
177                  TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
178          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
179                  TII.get(Hexagon::ADD_rr),
180                  dstReg).addReg(FrameReg).addReg(dstReg);
181        } else {
182          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
183                  TII.get(Hexagon::ADD_ri),
184                  dstReg).addReg(FrameReg).addImm(Offset);
185        }
186
187        MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
188        MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
189      } else if ((MI.getOpcode() == Hexagon::STriw_indexed) ||
190                 (MI.getOpcode() == Hexagon::STriw) ||
191                 (MI.getOpcode() == Hexagon::STrid) ||
192                 (MI.getOpcode() == Hexagon::STrih) ||
193                 (MI.getOpcode() == Hexagon::STrib) ||
194                 (MI.getOpcode() == Hexagon::STrid_f) ||
195                 (MI.getOpcode() == Hexagon::STriw_f)) {
196        // For stores, we need a reserved register. Change
197        // memw(r30 + #10000) = r0 to:
198        //
199        // rs = add(r30, #10000);
200        // memw(rs) = r0
201        unsigned resReg = HEXAGON_RESERVED_REG_1;
202
203        // Check if offset can fit in addi.
204        if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
205          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
206                  TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
207          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
208                  TII.get(Hexagon::ADD_rr),
209                  resReg).addReg(FrameReg).addReg(resReg);
210        } else {
211          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
212                  TII.get(Hexagon::ADD_ri),
213                  resReg).addReg(FrameReg).addImm(Offset);
214        }
215        MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,true);
216        MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
217      } else if (TII.isMemOp(&MI)) {
218        unsigned resReg = HEXAGON_RESERVED_REG_1;
219        if (!MFI.hasVarSizedObjects() &&
220            TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
221          MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(),
222                                                       false, false, true);
223          MI.getOperand(FIOperandNum+1).ChangeToImmediate(FrameSize+Offset);
224        } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
225          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
226                  TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
227          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
228                  TII.get(Hexagon::ADD_rr),
229                  resReg).addReg(FrameReg).addReg(resReg);
230          MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,
231                                                       true);
232          MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
233        } else {
234          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
235                  TII.get(Hexagon::ADD_ri),
236                  resReg).addReg(FrameReg).addImm(Offset);
237          MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,
238                                                       true);
239          MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
240        }
241      } else {
242        unsigned dstReg = MI.getOperand(0).getReg();
243        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
244                TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
245        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
246                TII.get(Hexagon::ADD_rr),
247                dstReg).addReg(FrameReg).addReg(dstReg);
248        // Can we delete MI??? r2 = add (r2, #0).
249        MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
250        MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
251      }
252    } else {
253      // If the offset is small enough to fit in the immediate field, directly
254      // encode it.
255      MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
256      MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
257    }
258  }
259
260}
261
262unsigned HexagonRegisterInfo::getRARegister() const {
263  return Hexagon::R31;
264}
265
266unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
267                                               &MF) const {
268  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
269  if (TFI->hasFP(MF)) {
270    return Hexagon::R30;
271  }
272
273  return Hexagon::R29;
274}
275
276unsigned HexagonRegisterInfo::getFrameRegister() const {
277  return Hexagon::R30;
278}
279
280unsigned HexagonRegisterInfo::getStackRegister() const {
281  return Hexagon::R29;
282}
283
284void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove>
285                                               &Moves)  const
286{
287  // VirtualFP = (R30 + #0).
288  unsigned FPReg = getFrameRegister();
289  MachineLocation Dst(MachineLocation::VirtualFP);
290  MachineLocation Src(FPReg, 0);
291  Moves.push_back(MachineMove(0, Dst, Src));
292}
293
294unsigned HexagonRegisterInfo::getEHExceptionRegister() const {
295  llvm_unreachable("What is the exception register");
296}
297
298unsigned HexagonRegisterInfo::getEHHandlerRegister() const {
299  llvm_unreachable("What is the exception handler register");
300}
301
302#define GET_REGINFO_TARGET_DESC
303#include "HexagonGenRegisterInfo.inc"
304