/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/XCore/XCoreRegisterInfo.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- XCoreRegisterInfo.cpp - XCore 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 XCore implementation of the MRegisterInfo class. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "XCoreRegisterInfo.h" |
15 | | #include "XCore.h" |
16 | | #include "XCoreInstrInfo.h" |
17 | | #include "XCoreMachineFunctionInfo.h" |
18 | | #include "XCoreSubtarget.h" |
19 | | #include "llvm/ADT/BitVector.h" |
20 | | #include "llvm/ADT/STLExtras.h" |
21 | | #include "llvm/CodeGen/MachineFrameInfo.h" |
22 | | #include "llvm/CodeGen/MachineFunction.h" |
23 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
24 | | #include "llvm/CodeGen/MachineModuleInfo.h" |
25 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
26 | | #include "llvm/CodeGen/RegisterScavenging.h" |
27 | | #include "llvm/IR/Function.h" |
28 | | #include "llvm/IR/Type.h" |
29 | | #include "llvm/Support/Debug.h" |
30 | | #include "llvm/Support/ErrorHandling.h" |
31 | | #include "llvm/Support/MathExtras.h" |
32 | | #include "llvm/Support/raw_ostream.h" |
33 | | #include "llvm/Target/TargetFrameLowering.h" |
34 | | #include "llvm/Target/TargetMachine.h" |
35 | | #include "llvm/Target/TargetOptions.h" |
36 | | |
37 | | using namespace llvm; |
38 | | |
39 | | #define DEBUG_TYPE "xcore-reg-info" |
40 | | |
41 | | #define GET_REGINFO_TARGET_DESC |
42 | | #include "XCoreGenRegisterInfo.inc" |
43 | | |
44 | | XCoreRegisterInfo::XCoreRegisterInfo() |
45 | 80 | : XCoreGenRegisterInfo(XCore::LR) { |
46 | 80 | } |
47 | | |
48 | | // helper functions |
49 | 78 | static inline bool isImmUs(unsigned val) { |
50 | 78 | return val <= 11; |
51 | 78 | } |
52 | | |
53 | 169 | static inline bool isImmU6(unsigned val) { |
54 | 169 | return val < (1 << 6); |
55 | 169 | } |
56 | | |
57 | 178 | static inline bool isImmU16(unsigned val) { |
58 | 178 | return val < (1 << 16); |
59 | 178 | } |
60 | | |
61 | | |
62 | | static void InsertFPImmInst(MachineBasicBlock::iterator II, |
63 | | const XCoreInstrInfo &TII, |
64 | 59 | unsigned Reg, unsigned FrameReg, int Offset ) { |
65 | 59 | MachineInstr &MI = *II; |
66 | 59 | MachineBasicBlock &MBB = *MI.getParent(); |
67 | 59 | DebugLoc dl = MI.getDebugLoc(); |
68 | 59 | |
69 | 59 | switch (MI.getOpcode()) { |
70 | 32 | case XCore::LDWFI: |
71 | 32 | BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg) |
72 | 32 | .addReg(FrameReg) |
73 | 32 | .addImm(Offset) |
74 | 32 | .addMemOperand(*MI.memoperands_begin()); |
75 | 32 | break; |
76 | 25 | case XCore::STWFI: |
77 | 25 | BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus)) |
78 | 25 | .addReg(Reg, getKillRegState(MI.getOperand(0).isKill())) |
79 | 25 | .addReg(FrameReg) |
80 | 25 | .addImm(Offset) |
81 | 25 | .addMemOperand(*MI.memoperands_begin()); |
82 | 25 | break; |
83 | 2 | case XCore::LDAWFI: |
84 | 2 | BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg) |
85 | 2 | .addReg(FrameReg) |
86 | 2 | .addImm(Offset); |
87 | 2 | break; |
88 | 0 | default: |
89 | 0 | llvm_unreachable("Unexpected Opcode"); |
90 | 59 | } |
91 | 59 | } |
92 | | |
93 | | static void InsertFPConstInst(MachineBasicBlock::iterator II, |
94 | | const XCoreInstrInfo &TII, |
95 | | unsigned Reg, unsigned FrameReg, |
96 | 19 | int Offset, RegScavenger *RS ) { |
97 | 19 | assert(RS && "requiresRegisterScavenging failed"); |
98 | 19 | MachineInstr &MI = *II; |
99 | 19 | MachineBasicBlock &MBB = *MI.getParent(); |
100 | 19 | DebugLoc dl = MI.getDebugLoc(); |
101 | 19 | unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0); |
102 | 19 | RS->setRegUsed(ScratchOffset); |
103 | 19 | TII.loadImmediate(MBB, II, ScratchOffset, Offset); |
104 | 19 | |
105 | 19 | switch (MI.getOpcode()) { |
106 | 8 | case XCore::LDWFI: |
107 | 8 | BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg) |
108 | 8 | .addReg(FrameReg) |
109 | 8 | .addReg(ScratchOffset, RegState::Kill) |
110 | 8 | .addMemOperand(*MI.memoperands_begin()); |
111 | 8 | break; |
112 | 8 | case XCore::STWFI: |
113 | 8 | BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r)) |
114 | 8 | .addReg(Reg, getKillRegState(MI.getOperand(0).isKill())) |
115 | 8 | .addReg(FrameReg) |
116 | 8 | .addReg(ScratchOffset, RegState::Kill) |
117 | 8 | .addMemOperand(*MI.memoperands_begin()); |
118 | 8 | break; |
119 | 3 | case XCore::LDAWFI: |
120 | 3 | BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg) |
121 | 3 | .addReg(FrameReg) |
122 | 3 | .addReg(ScratchOffset, RegState::Kill); |
123 | 3 | break; |
124 | 0 | default: |
125 | 0 | llvm_unreachable("Unexpected Opcode"); |
126 | 19 | } |
127 | 19 | } |
128 | | |
129 | | static void InsertSPImmInst(MachineBasicBlock::iterator II, |
130 | | const XCoreInstrInfo &TII, |
131 | 169 | unsigned Reg, int Offset) { |
132 | 169 | MachineInstr &MI = *II; |
133 | 169 | MachineBasicBlock &MBB = *MI.getParent(); |
134 | 169 | DebugLoc dl = MI.getDebugLoc(); |
135 | 169 | bool isU6 = isImmU6(Offset); |
136 | 169 | |
137 | 169 | switch (MI.getOpcode()) { |
138 | 0 | int NewOpcode; |
139 | 69 | case XCore::LDWFI: |
140 | 69 | NewOpcode = (isU6) ? XCore::LDWSP_ru668 : XCore::LDWSP_lru61 ; |
141 | 69 | BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg) |
142 | 69 | .addImm(Offset) |
143 | 69 | .addMemOperand(*MI.memoperands_begin()); |
144 | 69 | break; |
145 | 90 | case XCore::STWFI: |
146 | 90 | NewOpcode = (isU6) ? XCore::STWSP_ru690 : XCore::STWSP_lru60 ; |
147 | 90 | BuildMI(MBB, II, dl, TII.get(NewOpcode)) |
148 | 90 | .addReg(Reg, getKillRegState(MI.getOperand(0).isKill())) |
149 | 90 | .addImm(Offset) |
150 | 90 | .addMemOperand(*MI.memoperands_begin()); |
151 | 90 | break; |
152 | 10 | case XCore::LDAWFI: |
153 | 10 | NewOpcode = (isU6) ? XCore::LDAWSP_ru68 : XCore::LDAWSP_lru62 ; |
154 | 10 | BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg) |
155 | 10 | .addImm(Offset); |
156 | 10 | break; |
157 | 0 | default: |
158 | 0 | llvm_unreachable("Unexpected Opcode"); |
159 | 169 | } |
160 | 169 | } |
161 | | |
162 | | static void InsertSPConstInst(MachineBasicBlock::iterator II, |
163 | | const XCoreInstrInfo &TII, |
164 | 9 | unsigned Reg, int Offset, RegScavenger *RS ) { |
165 | 9 | assert(RS && "requiresRegisterScavenging failed"); |
166 | 9 | MachineInstr &MI = *II; |
167 | 9 | MachineBasicBlock &MBB = *MI.getParent(); |
168 | 9 | DebugLoc dl = MI.getDebugLoc(); |
169 | 9 | unsigned OpCode = MI.getOpcode(); |
170 | 9 | |
171 | 9 | unsigned ScratchBase; |
172 | 9 | if (OpCode==XCore::STWFI9 ) { |
173 | 6 | ScratchBase = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0); |
174 | 6 | RS->setRegUsed(ScratchBase); |
175 | 6 | } else |
176 | 3 | ScratchBase = Reg; |
177 | 9 | BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0); |
178 | 9 | unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0); |
179 | 9 | RS->setRegUsed(ScratchOffset); |
180 | 9 | TII.loadImmediate(MBB, II, ScratchOffset, Offset); |
181 | 9 | |
182 | 9 | switch (OpCode) { |
183 | 2 | case XCore::LDWFI: |
184 | 2 | BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg) |
185 | 2 | .addReg(ScratchBase, RegState::Kill) |
186 | 2 | .addReg(ScratchOffset, RegState::Kill) |
187 | 2 | .addMemOperand(*MI.memoperands_begin()); |
188 | 2 | break; |
189 | 6 | case XCore::STWFI: |
190 | 6 | BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r)) |
191 | 6 | .addReg(Reg, getKillRegState(MI.getOperand(0).isKill())) |
192 | 6 | .addReg(ScratchBase, RegState::Kill) |
193 | 6 | .addReg(ScratchOffset, RegState::Kill) |
194 | 6 | .addMemOperand(*MI.memoperands_begin()); |
195 | 6 | break; |
196 | 1 | case XCore::LDAWFI: |
197 | 1 | BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg) |
198 | 1 | .addReg(ScratchBase, RegState::Kill) |
199 | 1 | .addReg(ScratchOffset, RegState::Kill); |
200 | 1 | break; |
201 | 0 | default: |
202 | 0 | llvm_unreachable("Unexpected Opcode"); |
203 | 9 | } |
204 | 9 | } |
205 | | |
206 | 297 | bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) { |
207 | 297 | return MF.getMMI().hasDebugInfo() || |
208 | 295 | MF.getFunction()->needsUnwindTableEntry(); |
209 | 297 | } |
210 | | |
211 | | const MCPhysReg * |
212 | 1.72k | XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { |
213 | 1.72k | // The callee saved registers LR & FP are explicitly handled during |
214 | 1.72k | // emitPrologue & emitEpilogue and related functions. |
215 | 1.72k | static const MCPhysReg CalleeSavedRegs[] = { |
216 | 1.72k | XCore::R4, XCore::R5, XCore::R6, XCore::R7, |
217 | 1.72k | XCore::R8, XCore::R9, XCore::R10, |
218 | 1.72k | 0 |
219 | 1.72k | }; |
220 | 1.72k | static const MCPhysReg CalleeSavedRegsFP[] = { |
221 | 1.72k | XCore::R4, XCore::R5, XCore::R6, XCore::R7, |
222 | 1.72k | XCore::R8, XCore::R9, |
223 | 1.72k | 0 |
224 | 1.72k | }; |
225 | 1.72k | const XCoreFrameLowering *TFI = getFrameLowering(*MF); |
226 | 1.72k | if (TFI->hasFP(*MF)) |
227 | 142 | return CalleeSavedRegsFP; |
228 | 1.58k | return CalleeSavedRegs; |
229 | 1.58k | } |
230 | | |
231 | 588 | BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const { |
232 | 588 | BitVector Reserved(getNumRegs()); |
233 | 588 | const XCoreFrameLowering *TFI = getFrameLowering(MF); |
234 | 588 | |
235 | 588 | Reserved.set(XCore::CP); |
236 | 588 | Reserved.set(XCore::DP); |
237 | 588 | Reserved.set(XCore::SP); |
238 | 588 | Reserved.set(XCore::LR); |
239 | 588 | if (TFI->hasFP(MF)588 ) { |
240 | 59 | Reserved.set(XCore::R10); |
241 | 59 | } |
242 | 588 | return Reserved; |
243 | 588 | } |
244 | | |
245 | | bool |
246 | 553 | XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { |
247 | 553 | return true; |
248 | 553 | } |
249 | | |
250 | | bool |
251 | 266 | XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const { |
252 | 266 | return true; |
253 | 266 | } |
254 | | |
255 | | bool |
256 | 20 | XCoreRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const { |
257 | 20 | return false; |
258 | 20 | } |
259 | | |
260 | | void |
261 | | XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, |
262 | | int SPAdj, unsigned FIOperandNum, |
263 | 256 | RegScavenger *RS) const { |
264 | 256 | assert(SPAdj == 0 && "Unexpected"); |
265 | 256 | MachineInstr &MI = *II; |
266 | 256 | MachineOperand &FrameOp = MI.getOperand(FIOperandNum); |
267 | 256 | int FrameIndex = FrameOp.getIndex(); |
268 | 256 | |
269 | 256 | MachineFunction &MF = *MI.getParent()->getParent(); |
270 | 256 | const XCoreInstrInfo &TII = |
271 | 256 | *static_cast<const XCoreInstrInfo *>(MF.getSubtarget().getInstrInfo()); |
272 | 256 | |
273 | 256 | const XCoreFrameLowering *TFI = getFrameLowering(MF); |
274 | 256 | int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex); |
275 | 256 | int StackSize = MF.getFrameInfo().getStackSize(); |
276 | 256 | |
277 | | #ifndef NDEBUG |
278 | | DEBUG(errs() << "\nFunction : " |
279 | | << MF.getName() << "\n"); |
280 | | DEBUG(errs() << "<--------->\n"); |
281 | | DEBUG(MI.print(errs())); |
282 | | DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n"); |
283 | | DEBUG(errs() << "FrameOffset : " << Offset << "\n"); |
284 | | DEBUG(errs() << "StackSize : " << StackSize << "\n"); |
285 | | #endif |
286 | | |
287 | 256 | Offset += StackSize; |
288 | 256 | |
289 | 256 | unsigned FrameReg = getFrameRegister(MF); |
290 | 256 | |
291 | 256 | // Special handling of DBG_VALUE instructions. |
292 | 256 | if (MI.isDebugValue()256 ) { |
293 | 0 | MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/); |
294 | 0 | MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); |
295 | 0 | return; |
296 | 0 | } |
297 | 256 | |
298 | 256 | // fold constant into offset. |
299 | 256 | Offset += MI.getOperand(FIOperandNum + 1).getImm(); |
300 | 256 | MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); |
301 | 256 | |
302 | 256 | assert(Offset%4 == 0 && "Misaligned stack offset"); |
303 | 256 | DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); |
304 | 256 | Offset/=4; |
305 | 256 | |
306 | 256 | unsigned Reg = MI.getOperand(0).getReg(); |
307 | 256 | assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand"); |
308 | 256 | |
309 | 256 | if (TFI->hasFP(MF)256 ) { |
310 | 78 | if (isImmUs(Offset)) |
311 | 59 | InsertFPImmInst(II, TII, Reg, FrameReg, Offset); |
312 | 78 | else |
313 | 19 | InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS); |
314 | 256 | } else { |
315 | 178 | if (isImmU16(Offset)) |
316 | 169 | InsertSPImmInst(II, TII, Reg, Offset); |
317 | 178 | else |
318 | 9 | InsertSPConstInst(II, TII, Reg, Offset, RS); |
319 | 178 | } |
320 | 256 | // Erase old instruction. |
321 | 256 | MachineBasicBlock &MBB = *MI.getParent(); |
322 | 256 | MBB.erase(II); |
323 | 256 | } |
324 | | |
325 | | |
326 | 276 | unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const { |
327 | 276 | const XCoreFrameLowering *TFI = getFrameLowering(MF); |
328 | 276 | |
329 | 276 | return TFI->hasFP(MF) ? XCore::R1086 : XCore::SP190 ; |
330 | 276 | } |