HexagonRegisterInfo.cpp revision d410eaba04211d53a523a518a5e315eb24c1072f
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    return CalleeSavedRegsV3;
67  }
68  llvm_unreachable("Callee saved registers requested for unknown architecture "
69                   "version");
70}
71
72BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
73  const {
74  BitVector Reserved(getNumRegs());
75  Reserved.set(HEXAGON_RESERVED_REG_1);
76  Reserved.set(HEXAGON_RESERVED_REG_2);
77  Reserved.set(Hexagon::R29);
78  Reserved.set(Hexagon::R30);
79  Reserved.set(Hexagon::R31);
80  Reserved.set(Hexagon::D14);
81  Reserved.set(Hexagon::D15);
82  Reserved.set(Hexagon::LC0);
83  Reserved.set(Hexagon::LC1);
84  Reserved.set(Hexagon::SA0);
85  Reserved.set(Hexagon::SA1);
86  return Reserved;
87}
88
89
90const TargetRegisterClass* const*
91HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
92  static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = {
93    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
94    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
95    };
96  static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = {
97    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
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  };
104
105  switch(Subtarget.getHexagonArchVersion()) {
106  case HexagonSubtarget::V1:
107    break;
108  case HexagonSubtarget::V2:
109    return CalleeSavedRegClassesV2;
110  case HexagonSubtarget::V3:
111  case HexagonSubtarget::V4:
112    return CalleeSavedRegClassesV3;
113  }
114  llvm_unreachable("Callee saved register classes requested for unknown "
115                   "architecture version");
116}
117
118void HexagonRegisterInfo::
119eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
120                              MachineBasicBlock::iterator I) const {
121  MachineInstr &MI = *I;
122
123  if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) {
124    // Hexagon_TODO: add code
125  } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) {
126    // Hexagon_TODO: add code
127  } else {
128    llvm_unreachable("Cannot handle this call frame pseudo instruction");
129  }
130  MBB.erase(I);
131}
132
133void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
134                                            int SPAdj, RegScavenger *RS) const {
135
136  //
137  // Hexagon_TODO: Do we need to enforce this for Hexagon?
138  assert(SPAdj == 0 && "Unexpected");
139
140
141  unsigned i = 0;
142  MachineInstr &MI = *II;
143  while (!MI.getOperand(i).isFI()) {
144    ++i;
145    assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
146  }
147
148  int FrameIndex = MI.getOperand(i).getIndex();
149
150  // Addressable stack objects are accessed using neg. offsets from %fp.
151  MachineFunction &MF = *MI.getParent()->getParent();
152  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
153  MachineFrameInfo &MFI = *MF.getFrameInfo();
154
155  unsigned FrameReg = getFrameRegister(MF);
156  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
157  if (!TFI->hasFP(MF)) {
158    // We will not reserve space on the stack for the lr and fp registers.
159    Offset -= 2 * Hexagon_WordSize;
160  }
161
162  const unsigned FrameSize = MFI.getStackSize();
163
164  if (!MFI.hasVarSizedObjects() &&
165      TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
166      !TII.isSpillPredRegOp(&MI)) {
167    // Replace frame index with a stack pointer reference.
168    MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true);
169    MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
170  } else {
171    // Replace frame index with a frame pointer reference.
172    if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
173
174      // If the offset overflows, then correct it.
175      //
176      // For loads, we do not need a reserved register
177      // r0 = memw(r30 + #10000) to:
178      //
179      // r0 = add(r30, #10000)
180      // r0 = memw(r0)
181      if ( (MI.getOpcode() == Hexagon::LDriw)  ||
182           (MI.getOpcode() == Hexagon::LDrid) ||
183           (MI.getOpcode() == Hexagon::LDrih) ||
184           (MI.getOpcode() == Hexagon::LDriuh) ||
185           (MI.getOpcode() == Hexagon::LDrib) ||
186           (MI.getOpcode() == Hexagon::LDriub) ) {
187        unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
188          *getSubRegisters(MI.getOperand(0).getReg()) :
189          MI.getOperand(0).getReg();
190
191        // Check if offset can fit in addi.
192        if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
193          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
194                  TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
195          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
196                  TII.get(Hexagon::ADD_rr),
197                  dstReg).addReg(FrameReg).addReg(dstReg);
198        } else {
199          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
200                  TII.get(Hexagon::ADD_ri),
201                  dstReg).addReg(FrameReg).addImm(Offset);
202        }
203
204        MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
205        MI.getOperand(i+1).ChangeToImmediate(0);
206      } else if ((MI.getOpcode() == Hexagon::STriw) ||
207                 (MI.getOpcode() == Hexagon::STrid) ||
208                 (MI.getOpcode() == Hexagon::STrih) ||
209                 (MI.getOpcode() == Hexagon::STrib)) {
210        // For stores, we need a reserved register. Change
211        // memw(r30 + #10000) = r0 to:
212        //
213        // rs = add(r30, #10000);
214        // memw(rs) = r0
215        unsigned resReg = HEXAGON_RESERVED_REG_1;
216
217        // Check if offset can fit in addi.
218        if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
219          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
220                  TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
221          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
222                  TII.get(Hexagon::ADD_rr),
223                  resReg).addReg(FrameReg).addReg(resReg);
224        } else {
225          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
226                  TII.get(Hexagon::ADD_ri),
227                  resReg).addReg(FrameReg).addImm(Offset);
228        }
229        MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
230        MI.getOperand(i+1).ChangeToImmediate(0);
231      } else if (TII.isMemOp(&MI)) {
232        unsigned resReg = HEXAGON_RESERVED_REG_1;
233        if (!MFI.hasVarSizedObjects() &&
234            TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
235          MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false,
236                                            true);
237          MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
238        } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
239          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
240                  TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
241          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
242                  TII.get(Hexagon::ADD_rr),
243                  resReg).addReg(FrameReg).addReg(resReg);
244          MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
245          MI.getOperand(i+1).ChangeToImmediate(0);
246        } else {
247          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
248                  TII.get(Hexagon::ADD_ri),
249                  resReg).addReg(FrameReg).addImm(Offset);
250          MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
251          MI.getOperand(i+1).ChangeToImmediate(0);
252        }
253      } else {
254        unsigned dstReg = MI.getOperand(0).getReg();
255        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
256                TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
257        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
258                TII.get(Hexagon::ADD_rr),
259                dstReg).addReg(FrameReg).addReg(dstReg);
260        // Can we delete MI??? r2 = add (r2, #0).
261        MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
262        MI.getOperand(i+1).ChangeToImmediate(0);
263      }
264    } else {
265      // If the offset is small enough to fit in the immediate field, directly
266      // encode it.
267      MI.getOperand(i).ChangeToRegister(FrameReg, false);
268      MI.getOperand(i+1).ChangeToImmediate(Offset);
269    }
270  }
271
272}
273
274unsigned HexagonRegisterInfo::getRARegister() const {
275  return Hexagon::R31;
276}
277
278unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
279                                               &MF) const {
280  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
281  if (TFI->hasFP(MF)) {
282    return Hexagon::R30;
283  }
284
285  return Hexagon::R29;
286}
287
288unsigned HexagonRegisterInfo::getFrameRegister() const {
289  return Hexagon::R30;
290}
291
292unsigned HexagonRegisterInfo::getStackRegister() const {
293  return Hexagon::R29;
294}
295
296void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove>
297                                               &Moves)  const
298{
299  // VirtualFP = (R30 + #0).
300  unsigned FPReg = getFrameRegister();
301  MachineLocation Dst(MachineLocation::VirtualFP);
302  MachineLocation Src(FPReg, 0);
303  Moves.push_back(MachineMove(0, Dst, Src));
304}
305
306unsigned HexagonRegisterInfo::getEHExceptionRegister() const {
307  llvm_unreachable("What is the exception register");
308}
309
310unsigned HexagonRegisterInfo::getEHHandlerRegister() const {
311  llvm_unreachable("What is the exception handler register");
312}
313
314#define GET_REGINFO_TARGET_DESC
315#include "HexagonGenRegisterInfo.inc"
316