HexagonRegisterInfo.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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/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/Support/CommandLine.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Target/TargetInstrInfo.h"
35#include "llvm/Target/TargetMachine.h"
36#include "llvm/Target/TargetOptions.h"
37
38using namespace llvm;
39
40
41HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st)
42  : HexagonGenRegisterInfo(Hexagon::R31),
43    Subtarget(st) {
44}
45
46const MCPhysReg *
47HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
48  static const MCPhysReg CalleeSavedRegsV2[] = {
49    Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
50  };
51  static const MCPhysReg CalleeSavedRegsV3[] = {
52    Hexagon::R16,   Hexagon::R17,   Hexagon::R18,   Hexagon::R19,
53    Hexagon::R20,   Hexagon::R21,   Hexagon::R22,   Hexagon::R23,
54    Hexagon::R24,   Hexagon::R25,   Hexagon::R26,   Hexagon::R27, 0
55  };
56
57  switch(Subtarget.getHexagonArchVersion()) {
58  case HexagonSubtarget::V1:
59    break;
60  case HexagonSubtarget::V2:
61    return CalleeSavedRegsV2;
62  case HexagonSubtarget::V3:
63  case HexagonSubtarget::V4:
64  case HexagonSubtarget::V5:
65    return CalleeSavedRegsV3;
66  }
67  llvm_unreachable("Callee saved registers requested for unknown architecture "
68                   "version");
69}
70
71BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
72  const {
73  BitVector Reserved(getNumRegs());
74  Reserved.set(HEXAGON_RESERVED_REG_1);
75  Reserved.set(HEXAGON_RESERVED_REG_2);
76  Reserved.set(Hexagon::R29);
77  Reserved.set(Hexagon::R30);
78  Reserved.set(Hexagon::R31);
79  Reserved.set(Hexagon::D14);
80  Reserved.set(Hexagon::D15);
81  Reserved.set(Hexagon::LC0);
82  Reserved.set(Hexagon::LC1);
83  Reserved.set(Hexagon::SA0);
84  Reserved.set(Hexagon::SA1);
85  return Reserved;
86}
87
88
89const TargetRegisterClass* const*
90HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
91  static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = {
92    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
93    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
94    };
95  static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = {
96    &Hexagon::IntRegsRegClass,     &Hexagon::IntRegsRegClass,
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  };
103
104  switch(Subtarget.getHexagonArchVersion()) {
105  case HexagonSubtarget::V1:
106    break;
107  case HexagonSubtarget::V2:
108    return CalleeSavedRegClassesV2;
109  case HexagonSubtarget::V3:
110  case HexagonSubtarget::V4:
111  case HexagonSubtarget::V5:
112    return CalleeSavedRegClassesV3;
113  }
114  llvm_unreachable("Callee saved register classes requested for unknown "
115                   "architecture version");
116}
117
118void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
119                                              int SPAdj, unsigned FIOperandNum,
120                                              RegScavenger *RS) const {
121  //
122  // Hexagon_TODO: Do we need to enforce this for Hexagon?
123  assert(SPAdj == 0 && "Unexpected");
124
125  MachineInstr &MI = *II;
126  int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
127
128  // Addressable stack objects are accessed using neg. offsets from %fp.
129  MachineFunction &MF = *MI.getParent()->getParent();
130  const HexagonInstrInfo &TII =
131    *static_cast<const HexagonInstrInfo*>(MF.getTarget().getInstrInfo());
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        // use the constant extender if the instruction provides it
219        // and we are V4TOps.
220        if (Subtarget.hasV4TOps()) {
221          if (TII.isConstExtended(&MI)) {
222            MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
223            MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
224            TII.immediateExtend(&MI);
225          } else {
226            llvm_unreachable("Need to implement for memops");
227          }
228        } else {
229          // Only V3 and older instructions here.
230          unsigned ResReg = HEXAGON_RESERVED_REG_1;
231          if (!MFI.hasVarSizedObjects() &&
232              TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
233            MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(),
234                                                         false, false, false);
235            MI.getOperand(FIOperandNum+1).ChangeToImmediate(FrameSize+Offset);
236          } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
237            BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
238                    TII.get(Hexagon::CONST32_Int_Real), ResReg).addImm(Offset);
239            BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
240                    TII.get(Hexagon::ADD_rr), ResReg).addReg(FrameReg).
241              addReg(ResReg);
242            MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false,
243                                                         true);
244            MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
245          } else {
246            BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
247                    TII.get(Hexagon::ADD_ri), ResReg).addReg(FrameReg).
248              addImm(Offset);
249            MI.getOperand(FIOperandNum).ChangeToRegister(ResReg, false, false,
250                                                         true);
251            MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
252          }
253        }
254      } else {
255        unsigned dstReg = MI.getOperand(0).getReg();
256        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
257                TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
258        BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
259                TII.get(Hexagon::ADD_rr),
260                dstReg).addReg(FrameReg).addReg(dstReg);
261        // Can we delete MI??? r2 = add (r2, #0).
262        MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
263        MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
264      }
265    } else {
266      // If the offset is small enough to fit in the immediate field, directly
267      // encode it.
268      MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
269      MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
270    }
271  }
272
273}
274
275unsigned HexagonRegisterInfo::getRARegister() const {
276  return Hexagon::R31;
277}
278
279unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
280                                               &MF) const {
281  const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
282  if (TFI->hasFP(MF)) {
283    return Hexagon::R30;
284  }
285
286  return Hexagon::R29;
287}
288
289unsigned HexagonRegisterInfo::getFrameRegister() const {
290  return Hexagon::R30;
291}
292
293unsigned HexagonRegisterInfo::getStackRegister() const {
294  return Hexagon::R29;
295}
296
297#define GET_REGINFO_TARGET_DESC
298#include "HexagonGenRegisterInfo.inc"
299