40a25b661676500e506e2a1f9e0beb1c64efa2ed
[oota-llvm.git] / lib / Target / AArch64 / AArch64RegisterInfo.cpp
1 //===- AArch64RegisterInfo.cpp - AArch64 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 AArch64 implementation of the TargetRegisterInfo
11 // class.
12 //
13 //===----------------------------------------------------------------------===//
14
15
16 #include "AArch64RegisterInfo.h"
17 #include "AArch64FrameLowering.h"
18 #include "AArch64MachineFunctionInfo.h"
19 #include "AArch64TargetMachine.h"
20 #include "MCTargetDesc/AArch64MCTargetDesc.h"
21 #include "llvm/ADT/BitVector.h"
22 #include "llvm/CodeGen/MachineFrameInfo.h"
23 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/RegisterScavenging.h"
26
27 #define GET_REGINFO_TARGET_DESC
28 #include "AArch64GenRegisterInfo.inc"
29
30 using namespace llvm;
31
32 AArch64RegisterInfo::AArch64RegisterInfo()
33   : AArch64GenRegisterInfo(AArch64::X30) {
34 }
35
36 const MCPhysReg *
37 AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
38   return CSR_PCS_SaveList;
39 }
40
41 const uint32_t*
42 AArch64RegisterInfo::getCallPreservedMask(CallingConv::ID) const {
43   return CSR_PCS_RegMask;
44 }
45
46 const uint32_t *AArch64RegisterInfo::getTLSDescCallPreservedMask() const {
47   return TLSDesc_RegMask;
48 }
49
50 const TargetRegisterClass *
51 AArch64RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
52   if (RC == &AArch64::FlagClassRegClass)
53     return &AArch64::GPR64RegClass;
54
55   return RC;
56 }
57
58
59
60 BitVector
61 AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
62   BitVector Reserved(getNumRegs());
63   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
64
65   Reserved.set(AArch64::XSP);
66   Reserved.set(AArch64::WSP);
67
68   Reserved.set(AArch64::XZR);
69   Reserved.set(AArch64::WZR);
70
71   if (TFI->hasFP(MF)) {
72     Reserved.set(AArch64::X29);
73     Reserved.set(AArch64::W29);
74   }
75
76   return Reserved;
77 }
78
79 static bool hasFrameOffset(int opcode) {
80   return opcode != AArch64::LD1x2_8B  && opcode != AArch64::LD1x3_8B  &&
81          opcode != AArch64::LD1x4_8B  && opcode != AArch64::ST1x2_8B  &&
82          opcode != AArch64::ST1x3_8B  && opcode != AArch64::ST1x4_8B  &&
83          opcode != AArch64::LD1x2_16B && opcode != AArch64::LD1x3_16B &&
84          opcode != AArch64::LD1x4_16B && opcode != AArch64::ST1x2_16B &&
85          opcode != AArch64::ST1x3_16B && opcode != AArch64::ST1x4_16B;
86 }
87
88 void
89 AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI,
90                                          int SPAdj,
91                                          unsigned FIOperandNum,
92                                          RegScavenger *RS) const {
93   assert(SPAdj == 0 && "Cannot deal with nonzero SPAdj yet");
94   MachineInstr &MI = *MBBI;
95   MachineBasicBlock &MBB = *MI.getParent();
96   MachineFunction &MF = *MBB.getParent();
97   MachineFrameInfo *MFI = MF.getFrameInfo();
98   const AArch64FrameLowering *TFI =
99    static_cast<const AArch64FrameLowering *>(MF.getTarget().getFrameLowering());
100
101   // In order to work out the base and offset for addressing, the FrameLowering
102   // code needs to know (sometimes) whether the instruction is storing/loading a
103   // callee-saved register, or whether it's a more generic
104   // operation. Fortunately the frame indices are used *only* for that purpose
105   // and are contiguous, so we can check here.
106   const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
107   int MinCSFI = 0;
108   int MaxCSFI = -1;
109
110   if (CSI.size()) {
111     MinCSFI = CSI[0].getFrameIdx();
112     MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
113   }
114
115   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
116   bool IsCalleeSaveOp = FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI;
117
118   unsigned FrameReg;
119   int64_t Offset;
120   Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj,
121                                            IsCalleeSaveOp);
122   // A vector load/store instruction doesn't have an offset operand.
123   bool HasOffsetOp = hasFrameOffset(MI.getOpcode());
124   if (HasOffsetOp)
125     Offset += MI.getOperand(FIOperandNum + 1).getImm();
126
127   // DBG_VALUE instructions have no real restrictions so they can be handled
128   // easily.
129   if (MI.isDebugValue()) {
130     MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/ false);
131     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
132     return;
133   }
134
135   const AArch64InstrInfo &TII =
136     *static_cast<const AArch64InstrInfo*>(MF.getTarget().getInstrInfo());
137   int MinOffset, MaxOffset, OffsetScale;
138   if (MI.getOpcode() == AArch64::ADDxxi_lsl0_s || !HasOffsetOp) {
139     MinOffset = 0;
140     MaxOffset = 0xfff;
141     OffsetScale = 1;
142   } else {
143     // Load/store of a stack object
144     TII.getAddressConstraints(MI, OffsetScale, MinOffset, MaxOffset);
145   }
146
147   // There are two situations we don't use frame + offset directly in the
148   // instruction:
149   // (1) The offset can't really be scaled
150   // (2) Can't encode offset as it doesn't have an offset operand
151   if ((Offset % OffsetScale != 0 || Offset < MinOffset || Offset > MaxOffset) ||
152       (!HasOffsetOp && Offset != 0)) {
153     unsigned BaseReg =
154       MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
155     emitRegUpdate(MBB, MBBI, MBBI->getDebugLoc(), TII,
156                   BaseReg, FrameReg, BaseReg, Offset);
157     FrameReg = BaseReg;
158     Offset = 0;
159   }
160
161   // Negative offsets are expected if we address from FP, but for
162   // now this checks nothing has gone horribly wrong.
163   assert(Offset >= 0 && "Unexpected negative offset from SP");
164
165   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false, false, true);
166   if (HasOffsetOp)
167     MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset / OffsetScale);
168 }
169
170 unsigned
171 AArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
172   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
173
174   if (TFI->hasFP(MF))
175     return AArch64::X29;
176   else
177     return AArch64::XSP;
178 }
179
180 bool
181 AArch64RegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
182   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
183   const AArch64FrameLowering *AFI
184     = static_cast<const AArch64FrameLowering*>(TFI);
185   return AFI->useFPForAddressing(MF);
186 }