HexagonRegisterInfo.cpp revision 263508
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/ADT/BitVector.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineFunctionPass.h"
25#include "llvm/CodeGen/MachineFrameInfo.h"
26#include "llvm/CodeGen/MachineRegisterInfo.h"
27#include "llvm/CodeGen/PseudoSourceValue.h"
28#include "llvm/CodeGen/RegisterScavenging.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/Type.h"
31#include "llvm/MC/MachineLocation.h"
32#include "llvm/Target/TargetInstrInfo.h"
33#include "llvm/Target/TargetMachine.h"
34#include "llvm/Target/TargetOptions.h"
35#include "llvm/Support/CommandLine.h"
36#include "llvm/Support/ErrorHandling.h"
37
38using namespace llvm;
39
40
41HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st)
42  : HexagonGenRegisterInfo(Hexagon::R31),
43    Subtarget(st) {
44}
45
46const uint16_t* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction
47                                                        *MF)
48  const {
49  static const uint16_t CalleeSavedRegsV2[] = {
50    Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
51  };
52  static const uint16_t CalleeSavedRegsV3[] = {
53    Hexagon::R16,   Hexagon::R17,   Hexagon::R18,   Hexagon::R19,
54    Hexagon::R20,   Hexagon::R21,   Hexagon::R22,   Hexagon::R23,
55    Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
56  };
57
58  switch(Subtarget.getHexagonArchVersion()) {
59  case HexagonSubtarget::V1:
60    break;
61  case HexagonSubtarget::V2:
62    return CalleeSavedRegsV2;
63  case HexagonSubtarget::V3:
64  case HexagonSubtarget::V4:
65  case HexagonSubtarget::V5:
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  case HexagonSubtarget::V5:
113    return CalleeSavedRegClassesV3;
114  }
115  llvm_unreachable("Callee saved register classes requested for unknown "
116                   "architecture version");
117}
118
119void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
120                                              int SPAdj, unsigned FIOperandNum,
121                                              RegScavenger *RS) const {
122  //
123  // Hexagon_TODO: Do we need to enforce this for Hexagon?
124  assert(SPAdj == 0 && "Unexpected");
125
126  MachineInstr &MI = *II;
127  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
128
129  // Addressable stack objects are accessed using neg. offsets from %fp.
130  MachineFunction &MF = *MI.getParent()->getParent();
131  const HexagonInstrInfo &TII =
132    *static_cast<const HexagonInstrInfo*>(MF.getTarget().getInstrInfo());
133  int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
134  MachineFrameInfo &MFI = *MF.getFrameInfo();
135
136  unsigned FrameReg = getFrameRegister(MF);
137  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
138  if (!TFI->hasFP(MF)) {
139    // We will not reserve space on the stack for the lr and fp registers.
140    Offset -= 2 * Hexagon_WordSize;
141  }
142
143  const unsigned FrameSize = MFI.getStackSize();
144
145  if (!MFI.hasVarSizedObjects() &&
146      TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
147      !TII.isSpillPredRegOp(&MI)) {
148    // Replace frame index with a stack pointer reference.
149    MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), false,
150                                                 false, true);
151    MI.getOperand(FIOperandNum + 1).ChangeToImmediate(FrameSize+Offset);
152  } else {
153    // Replace frame index with a frame pointer reference.
154    if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
155
156      // If the offset overflows, then correct it.
157      //
158      // For loads, we do not need a reserved register
159      // r0 = memw(r30 + #10000) to:
160      //
161      // r0 = add(r30, #10000)
162      // r0 = memw(r0)
163      if ( (MI.getOpcode() == Hexagon::LDriw)  ||
164           (MI.getOpcode() == Hexagon::LDrid)   ||
165           (MI.getOpcode() == Hexagon::LDrih)   ||
166           (MI.getOpcode() == Hexagon::LDriuh)  ||
167           (MI.getOpcode() == Hexagon::LDrib)   ||
168           (MI.getOpcode() == Hexagon::LDriub)  ||
169           (MI.getOpcode() == Hexagon::LDriw_f) ||
170           (MI.getOpcode() == Hexagon::LDrid_f)) {
171        unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
172          getSubReg(MI.getOperand(0).getReg(), Hexagon::subreg_loreg) :
173          MI.getOperand(0).getReg();
174
175        // Check if offset can fit in addi.
176        if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
177          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
178                  TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
179          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
180                  TII.get(Hexagon::ADD_rr),
181                  dstReg).addReg(FrameReg).addReg(dstReg);
182        } else {
183          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
184                  TII.get(Hexagon::ADD_ri),
185                  dstReg).addReg(FrameReg).addImm(Offset);
186        }
187
188        MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
189        MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
190      } else if ((MI.getOpcode() == Hexagon::STriw_indexed) ||
191                 (MI.getOpcode() == Hexagon::STriw) ||
192                 (MI.getOpcode() == Hexagon::STrid) ||
193                 (MI.getOpcode() == Hexagon::STrih) ||
194                 (MI.getOpcode() == Hexagon::STrib) ||
195                 (MI.getOpcode() == Hexagon::STrid_f) ||
196                 (MI.getOpcode() == Hexagon::STriw_f)) {
197        // For stores, we need a reserved register. Change
198        // memw(r30 + #10000) = r0 to:
199        //
200        // rs = add(r30, #10000);
201        // memw(rs) = r0
202        unsigned resReg = HEXAGON_RESERVED_REG_1;
203
204        // Check if offset can fit in addi.
205        if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
206          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
207                  TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
208          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
209                  TII.get(Hexagon::ADD_rr),
210                  resReg).addReg(FrameReg).addReg(resReg);
211        } else {
212          BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
213                  TII.get(Hexagon::ADD_ri),
214                  resReg).addReg(FrameReg).addImm(Offset);
215        }
216        MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,true);
217        MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
218      } else if (TII.isMemOp(&MI)) {
219        // use the constant extender if the instruction provides it
220        // and we are V4TOps.
221        if (Subtarget.hasV4TOps()) {
222          if (TII.isConstExtended(&MI)) {
223            MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
224            MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
225            TII.immediateExtend(&MI);
226          } else {
227            llvm_unreachable("Need to implement for memops");
228          }
229        } else {
230          // Only V3 and older instructions here.
231          unsigned ResReg = HEXAGON_RESERVED_REG_1;
232          if (!MFI.hasVarSizedObjects() &&
233              TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
234            MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(),
235                                                         false, false, false);
236            MI.getOperand(FIOperandNum+1).ChangeToImmediate(FrameSize+Offset);
237          } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
238            BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
239                    TII.get(Hexagon::CONST32_Int_Real), ResReg).addImm(Offset);
240            BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
241                    TII.get(Hexagon::ADD_rr), ResReg).addReg(FrameReg).
242              addReg(ResReg);
243            MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false,
244                                                         true);
245            MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
246          } else {
247            BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
248                    TII.get(Hexagon::ADD_ri), ResReg).addReg(FrameReg).
249              addImm(Offset);
250            MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false,
251                                                         true);
252            MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
253          }
254        }
255      } else {
256        unsigned dstReg = MI.getOperand(0).getReg();
257        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
258                TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
259        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
260                TII.get(Hexagon::ADD_rr),
261                dstReg).addReg(FrameReg).addReg(dstReg);
262        // Can we delete MI??? r2 = add (r2, #0).
263        MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
264        MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
265      }
266    } else {
267      // If the offset is small enough to fit in the immediate field, directly
268      // encode it.
269      MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
270      MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
271    }
272  }
273
274}
275
276unsigned HexagonRegisterInfo::getRARegister() const {
277  return Hexagon::R31;
278}
279
280unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
281                                               &MF) const {
282  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
283  if (TFI->hasFP(MF)) {
284    return Hexagon::R30;
285  }
286
287  return Hexagon::R29;
288}
289
290unsigned HexagonRegisterInfo::getFrameRegister() const {
291  return Hexagon::R30;
292}
293
294unsigned HexagonRegisterInfo::getStackRegister() const {
295  return Hexagon::R29;
296}
297
298#define GET_REGINFO_TARGET_DESC
299#include "HexagonGenRegisterInfo.inc"
300