LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HexagonRegisterInfo.cpp
Go to the documentation of this file.
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"
20 #include "llvm/ADT/BitVector.h"
21 #include "llvm/ADT/STLExtras.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/Type.h"
37 
38 using namespace llvm;
39 
40 
42  : HexagonGenRegisterInfo(Hexagon::R31),
43  Subtarget(st) {
44 }
45 
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 
60  break;
62  return CalleeSavedRegsV2;
66  return CalleeSavedRegsV3;
67  }
68  llvm_unreachable("Callee saved registers requested for unknown architecture "
69  "version");
70 }
71 
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 
90 const TargetRegisterClass* 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()) {
107  break;
109  return CalleeSavedRegClassesV2;
113  return CalleeSavedRegClassesV3;
114  }
115  llvm_unreachable("Callee saved register classes requested for unknown "
116  "architecture version");
117 }
118 
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 
277  return Hexagon::R31;
278 }
279 
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 
291  return Hexagon::R30;
292 }
293 
295  return Hexagon::R29;
296 }
297 
298 #define GET_REGINFO_TARGET_DESC
299 #include "HexagonGenRegisterInfo.inc"
bool isSpillPredRegOp(const MachineInstr *MI) const
const MachineFunction * getParent() const
BitVector & set()
Definition: BitVector.h:236
#define HEXAGON_RESERVED_REG_1
const HexagonArchEnum & getHexagonArchVersion() const
const TargetRegisterClass *const * getCalleeSavedRegClasses(const MachineFunction *MF=0) const
void ChangeToRegister(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
bool isConstExtended(MachineInstr *MI) const
#define HEXAGON_RESERVED_REG_2
#define Hexagon_WordSize
Definition: Hexagon.h:69
uint64_t getStackSize() const
BitVector getReservedRegs(const MachineFunction &MF) const
bool isMemOp(const MachineInstr *MI) const
const HexagonInstrInfo * TII
virtual bool hasFP(const MachineFunction &MF) const =0
#define llvm_unreachable(msg)
Abstract Stack Frame Information.
const MachineInstrBuilder & addImm(int64_t Val) const
bool isValidOffset(const int Opcode, const int Offset) const
int getOpcode() const
Definition: MachineInstr.h:261
void ChangeToImmediate(int64_t ImmVal)
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:119
bundle_iterator< MachineInstr, instr_iterator > iterator
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:267
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
virtual const TargetFrameLowering * getFrameLowering() const
int64_t getObjectOffset(int ObjectIdx) const
virtual const TargetInstrInfo * getInstrInfo() const
HexagonRegisterInfo(HexagonSubtarget &st)
MachineFrameInfo * getFrameInfo()
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=NULL) const
const TargetMachine & getTarget() const
bool hasVarSizedObjects() const
HexagonSubtarget & Subtarget
unsigned getReg() const
getReg - Returns the register number.
const uint16_t * getCalleeSavedRegs(const MachineFunction *MF=0) const
Code Generation virtual methods...
void immediateExtend(MachineInstr *MI) const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
DebugLoc getDebugLoc() const
Definition: MachineInstr.h:244