/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/ARM/ThumbRegisterInfo.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ThumbRegisterInfo.cpp - Thumb-1 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 Thumb-1 implementation of the TargetRegisterInfo |
11 | | // class. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "ThumbRegisterInfo.h" |
16 | | #include "ARMBaseInstrInfo.h" |
17 | | #include "ARMMachineFunctionInfo.h" |
18 | | #include "ARMSubtarget.h" |
19 | | #include "MCTargetDesc/ARMAddressingModes.h" |
20 | | #include "llvm/CodeGen/MachineConstantPool.h" |
21 | | #include "llvm/CodeGen/MachineFrameInfo.h" |
22 | | #include "llvm/CodeGen/MachineFunction.h" |
23 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
24 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
25 | | #include "llvm/CodeGen/RegisterScavenging.h" |
26 | | #include "llvm/IR/Constants.h" |
27 | | #include "llvm/IR/DerivedTypes.h" |
28 | | #include "llvm/IR/Function.h" |
29 | | #include "llvm/IR/LLVMContext.h" |
30 | | #include "llvm/Support/CommandLine.h" |
31 | | #include "llvm/Support/ErrorHandling.h" |
32 | | #include "llvm/Target/TargetFrameLowering.h" |
33 | | #include "llvm/Target/TargetMachine.h" |
34 | | |
35 | | namespace llvm { |
36 | | extern cl::opt<bool> ReuseFrameIndexVals; |
37 | | } |
38 | | |
39 | | using namespace llvm; |
40 | | |
41 | 3.35k | ThumbRegisterInfo::ThumbRegisterInfo() : ARMBaseRegisterInfo() {} |
42 | | |
43 | | const TargetRegisterClass * |
44 | | ThumbRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC, |
45 | 32.5k | const MachineFunction &MF) const { |
46 | 32.5k | if (!MF.getSubtarget<ARMSubtarget>().isThumb1Only()) |
47 | 28.5k | return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF); |
48 | 3.94k | |
49 | 3.94k | if (3.94k ARM::tGPRRegClass.hasSubClassEq(RC)3.94k ) |
50 | 3.94k | return &ARM::tGPRRegClass; |
51 | 2 | return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC, MF); |
52 | 2 | } |
53 | | |
54 | | const TargetRegisterClass * |
55 | | ThumbRegisterInfo::getPointerRegClass(const MachineFunction &MF, |
56 | 261 | unsigned Kind) const { |
57 | 261 | if (!MF.getSubtarget<ARMSubtarget>().isThumb1Only()) |
58 | 251 | return ARMBaseRegisterInfo::getPointerRegClass(MF, Kind); |
59 | 10 | return &ARM::tGPRRegClass; |
60 | 10 | } |
61 | | |
62 | | static void emitThumb1LoadConstPool(MachineBasicBlock &MBB, |
63 | | MachineBasicBlock::iterator &MBBI, |
64 | | const DebugLoc &dl, unsigned DestReg, |
65 | | unsigned SubIdx, int Val, |
66 | | ARMCC::CondCodes Pred, unsigned PredReg, |
67 | 81 | unsigned MIFlags) { |
68 | 81 | MachineFunction &MF = *MBB.getParent(); |
69 | 81 | const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); |
70 | 81 | const TargetInstrInfo &TII = *STI.getInstrInfo(); |
71 | 81 | MachineConstantPool *ConstantPool = MF.getConstantPool(); |
72 | 81 | const Constant *C = ConstantInt::get( |
73 | 81 | Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); |
74 | 81 | unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); |
75 | 81 | |
76 | 81 | BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci)) |
77 | 81 | .addReg(DestReg, getDefRegState(true), SubIdx) |
78 | 81 | .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg) |
79 | 81 | .setMIFlags(MIFlags); |
80 | 81 | } |
81 | | |
82 | | static void emitThumb2LoadConstPool(MachineBasicBlock &MBB, |
83 | | MachineBasicBlock::iterator &MBBI, |
84 | | const DebugLoc &dl, unsigned DestReg, |
85 | | unsigned SubIdx, int Val, |
86 | | ARMCC::CondCodes Pred, unsigned PredReg, |
87 | 0 | unsigned MIFlags) { |
88 | 0 | MachineFunction &MF = *MBB.getParent(); |
89 | 0 | const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); |
90 | 0 | MachineConstantPool *ConstantPool = MF.getConstantPool(); |
91 | 0 | const Constant *C = ConstantInt::get( |
92 | 0 | Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); |
93 | 0 | unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); |
94 | 0 |
|
95 | 0 | BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci)) |
96 | 0 | .addReg(DestReg, getDefRegState(true), SubIdx) |
97 | 0 | .addConstantPoolIndex(Idx) |
98 | 0 | .add(predOps(ARMCC::AL)) |
99 | 0 | .setMIFlags(MIFlags); |
100 | 0 | } |
101 | | |
102 | | /// emitLoadConstPool - Emits a load from constpool to materialize the |
103 | | /// specified immediate. |
104 | | void ThumbRegisterInfo::emitLoadConstPool( |
105 | | MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, |
106 | | const DebugLoc &dl, unsigned DestReg, unsigned SubIdx, int Val, |
107 | 81 | ARMCC::CondCodes Pred, unsigned PredReg, unsigned MIFlags) const { |
108 | 81 | MachineFunction &MF = *MBB.getParent(); |
109 | 81 | const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); |
110 | 81 | if (STI.isThumb1Only()81 ) { |
111 | 81 | assert((isARMLowRegister(DestReg) || isVirtualRegister(DestReg)) && |
112 | 81 | "Thumb1 does not have ldr to high register"); |
113 | 81 | return emitThumb1LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred, |
114 | 81 | PredReg, MIFlags); |
115 | 81 | } |
116 | 0 | return emitThumb2LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred, |
117 | 0 | PredReg, MIFlags); |
118 | 0 | } |
119 | | |
120 | | /// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize |
121 | | /// a destreg = basereg + immediate in Thumb code. Materialize the immediate |
122 | | /// in a register using mov / mvn sequences or load the immediate from a |
123 | | /// constpool entry. |
124 | | static void emitThumbRegPlusImmInReg( |
125 | | MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, |
126 | | const DebugLoc &dl, unsigned DestReg, unsigned BaseReg, int NumBytes, |
127 | | bool CanChangeCC, const TargetInstrInfo &TII, |
128 | 85 | const ARMBaseRegisterInfo &MRI, unsigned MIFlags = MachineInstr::NoFlags) { |
129 | 85 | MachineFunction &MF = *MBB.getParent(); |
130 | 85 | const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>(); |
131 | 85 | bool isHigh = !isARMLowRegister(DestReg) || |
132 | 16 | (BaseReg != 0 && 16 !isARMLowRegister(BaseReg)16 ); |
133 | 85 | bool isSub = false; |
134 | 85 | // Subtract doesn't have high register version. Load the negative value |
135 | 85 | // if either base or dest register is a high register. Also, if do not |
136 | 85 | // issue sub as part of the sequence if condition register is to be |
137 | 85 | // preserved. |
138 | 85 | if (NumBytes < 0 && 85 !isHigh34 && CanChangeCC0 ) { |
139 | 0 | isSub = true; |
140 | 0 | NumBytes = -NumBytes; |
141 | 0 | } |
142 | 85 | unsigned LdReg = DestReg; |
143 | 85 | if (DestReg == ARM::SP) |
144 | 85 | assert(BaseReg == ARM::SP && "Unexpected!"); |
145 | 85 | if (!isARMLowRegister(DestReg) && 85 !MRI.isVirtualRegister(DestReg)69 ) |
146 | 58 | LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); |
147 | 85 | |
148 | 85 | if (NumBytes <= 255 && 85 NumBytes >= 034 && CanChangeCC0 ) { |
149 | 0 | BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg) |
150 | 0 | .add(t1CondCodeOp()) |
151 | 0 | .addImm(NumBytes) |
152 | 0 | .setMIFlags(MIFlags); |
153 | 85 | } else if (85 NumBytes < 0 && 85 NumBytes >= -25534 && CanChangeCC0 ) { |
154 | 0 | BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg) |
155 | 0 | .add(t1CondCodeOp()) |
156 | 0 | .addImm(NumBytes) |
157 | 0 | .setMIFlags(MIFlags); |
158 | 0 | BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg) |
159 | 0 | .add(t1CondCodeOp()) |
160 | 0 | .addReg(LdReg, RegState::Kill) |
161 | 0 | .setMIFlags(MIFlags); |
162 | 85 | } else if (85 ST.genExecuteOnly()85 ) { |
163 | 4 | BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), LdReg) |
164 | 4 | .addImm(NumBytes).setMIFlags(MIFlags); |
165 | 4 | } else |
166 | 81 | MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0, |
167 | 81 | MIFlags); |
168 | 85 | |
169 | 85 | // Emit add / sub. |
170 | 0 | int Opc = (isSub) ? ARM::tSUBrr |
171 | 85 | : ((isHigh || 85 !CanChangeCC0 ) ? ARM::tADDhirr85 : ARM::tADDrr0 ); |
172 | 85 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); |
173 | 85 | if (Opc != ARM::tADDhirr) |
174 | 0 | MIB = MIB.add(t1CondCodeOp()); |
175 | 85 | if (DestReg == ARM::SP || 85 isSub27 ) |
176 | 58 | MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill); |
177 | 85 | else |
178 | 27 | MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill); |
179 | 85 | MIB.add(predOps(ARMCC::AL)); |
180 | 85 | } |
181 | | |
182 | | /// emitThumbRegPlusImmediate - Emits a series of instructions to materialize |
183 | | /// a destreg = basereg + immediate in Thumb code. Tries a series of ADDs or |
184 | | /// SUBs first, and uses a constant pool value if the instruction sequence would |
185 | | /// be too long. This is allowed to modify the condition flags. |
186 | | void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, |
187 | | MachineBasicBlock::iterator &MBBI, |
188 | | const DebugLoc &dl, unsigned DestReg, |
189 | | unsigned BaseReg, int NumBytes, |
190 | | const TargetInstrInfo &TII, |
191 | | const ARMBaseRegisterInfo &MRI, |
192 | 1.44k | unsigned MIFlags) { |
193 | 1.44k | bool isSub = NumBytes < 0; |
194 | 1.44k | unsigned Bytes = (unsigned)NumBytes; |
195 | 1.44k | if (isSub1.44k ) Bytes = -NumBytes388 ; |
196 | 1.44k | |
197 | 1.44k | int CopyOpc = 0; |
198 | 1.44k | unsigned CopyBits = 0; |
199 | 1.44k | unsigned CopyScale = 1; |
200 | 1.44k | bool CopyNeedsCC = false; |
201 | 1.44k | int ExtraOpc = 0; |
202 | 1.44k | unsigned ExtraBits = 0; |
203 | 1.44k | unsigned ExtraScale = 1; |
204 | 1.44k | bool ExtraNeedsCC = false; |
205 | 1.44k | |
206 | 1.44k | // Strategy: |
207 | 1.44k | // We need to select two types of instruction, maximizing the available |
208 | 1.44k | // immediate range of each. The instructions we use will depend on whether |
209 | 1.44k | // DestReg and BaseReg are low, high or the stack pointer. |
210 | 1.44k | // * CopyOpc - DestReg = BaseReg + imm |
211 | 1.44k | // This will be emitted once if DestReg != BaseReg, and never if |
212 | 1.44k | // DestReg == BaseReg. |
213 | 1.44k | // * ExtraOpc - DestReg = DestReg + imm |
214 | 1.44k | // This will be emitted as many times as necessary to add the |
215 | 1.44k | // full immediate. |
216 | 1.44k | // If the immediate ranges of these instructions are not large enough to cover |
217 | 1.44k | // NumBytes with a reasonable number of instructions, we fall back to using a |
218 | 1.44k | // value loaded from a constant pool. |
219 | 1.44k | if (DestReg == ARM::SP1.44k ) { |
220 | 1.13k | if (BaseReg == ARM::SP1.13k ) { |
221 | 1.13k | // sp -> sp |
222 | 1.13k | // Already in right reg, no copy needed |
223 | 1.13k | } else { |
224 | 0 | // low -> sp or high -> sp |
225 | 0 | CopyOpc = ARM::tMOVr; |
226 | 0 | CopyBits = 0; |
227 | 0 | } |
228 | 1.13k | ExtraOpc = isSub ? ARM::tSUBspi350 : ARM::tADDspi780 ; |
229 | 1.13k | ExtraBits = 7; |
230 | 1.13k | ExtraScale = 4; |
231 | 1.44k | } else if (316 isARMLowRegister(DestReg)316 ) { |
232 | 316 | if (BaseReg == ARM::SP316 ) { |
233 | 275 | // sp -> low |
234 | 275 | assert(!isSub && "Thumb1 does not have tSUBrSPi"); |
235 | 275 | CopyOpc = ARM::tADDrSPi; |
236 | 275 | CopyBits = 8; |
237 | 275 | CopyScale = 4; |
238 | 316 | } else if (41 DestReg == BaseReg41 ) { |
239 | 0 | // low -> same low |
240 | 0 | // Already in right reg, no copy needed |
241 | 41 | } else if (41 isARMLowRegister(BaseReg)41 ) { |
242 | 41 | // low -> different low |
243 | 41 | CopyOpc = isSub ? ARM::tSUBi338 : ARM::tADDi33 ; |
244 | 41 | CopyBits = 3; |
245 | 41 | CopyNeedsCC = true; |
246 | 0 | } else { |
247 | 0 | // high -> low |
248 | 0 | CopyOpc = ARM::tMOVr; |
249 | 0 | CopyBits = 0; |
250 | 0 | } |
251 | 316 | ExtraOpc = isSub ? ARM::tSUBi838 : ARM::tADDi8278 ; |
252 | 316 | ExtraBits = 8; |
253 | 316 | ExtraNeedsCC = true; |
254 | 0 | } else /* DestReg is high */ { |
255 | 0 | if (DestReg == BaseReg0 ) { |
256 | 0 | // high -> same high |
257 | 0 | // Already in right reg, no copy needed |
258 | 0 | } else { |
259 | 0 | // {low,high,sp} -> high |
260 | 0 | CopyOpc = ARM::tMOVr; |
261 | 0 | CopyBits = 0; |
262 | 0 | } |
263 | 316 | ExtraOpc = 0; |
264 | 316 | } |
265 | 1.44k | |
266 | 1.44k | // We could handle an unaligned immediate with an unaligned copy instruction |
267 | 1.44k | // and an aligned extra instruction, but this case is not currently needed. |
268 | 1.44k | assert(((Bytes & 3) == 0 || ExtraScale == 1) && |
269 | 1.44k | "Unaligned offset, but all instructions require alignment"); |
270 | 1.44k | |
271 | 1.44k | unsigned CopyRange = ((1 << CopyBits) - 1) * CopyScale; |
272 | 1.44k | // If we would emit the copy with an immediate of 0, just use tMOVr. |
273 | 1.44k | if (CopyOpc && 1.44k Bytes < CopyScale316 ) { |
274 | 49 | CopyOpc = ARM::tMOVr; |
275 | 49 | CopyScale = 1; |
276 | 49 | CopyNeedsCC = false; |
277 | 49 | CopyRange = 0; |
278 | 49 | } |
279 | 1.44k | unsigned ExtraRange = ((1 << ExtraBits) - 1) * ExtraScale; // per instruction |
280 | 1.44k | unsigned RequiredCopyInstrs = CopyOpc ? 1316 : 01.13k ; |
281 | 1.44k | unsigned RangeAfterCopy = (CopyRange > Bytes) ? 0215 : (Bytes - CopyRange)1.23k ; |
282 | 1.44k | |
283 | 1.44k | // We could handle this case when the copy instruction does not require an |
284 | 1.44k | // aligned immediate, but we do not currently do this. |
285 | 1.44k | assert(RangeAfterCopy % ExtraScale == 0 && |
286 | 1.44k | "Extra instruction requires immediate to be aligned"); |
287 | 1.44k | |
288 | 1.44k | unsigned RequiredExtraInstrs; |
289 | 1.44k | if (ExtraRange) |
290 | 1.44k | RequiredExtraInstrs = alignTo(RangeAfterCopy, ExtraRange) / ExtraRange; |
291 | 0 | else if (0 RangeAfterCopy > 00 ) |
292 | 0 | // We need an extra instruction but none is available |
293 | 0 | RequiredExtraInstrs = 1000000; |
294 | 0 | else |
295 | 0 | RequiredExtraInstrs = 0; |
296 | 1.44k | unsigned RequiredInstrs = RequiredCopyInstrs + RequiredExtraInstrs; |
297 | 1.44k | unsigned Threshold = (DestReg == ARM::SP) ? 31.13k : 2316 ; |
298 | 1.44k | |
299 | 1.44k | // Use a constant pool, if the sequence of ADDs/SUBs is too expensive. |
300 | 1.44k | if (RequiredInstrs > Threshold1.44k ) { |
301 | 61 | emitThumbRegPlusImmInReg(MBB, MBBI, dl, |
302 | 61 | DestReg, BaseReg, NumBytes, true, |
303 | 61 | TII, MRI, MIFlags); |
304 | 61 | return; |
305 | 61 | } |
306 | 1.38k | |
307 | 1.38k | // Emit zero or one copy instructions |
308 | 1.38k | if (1.38k CopyOpc1.38k ) { |
309 | 313 | unsigned CopyImm = std::min(Bytes, CopyRange) / CopyScale; |
310 | 313 | Bytes -= CopyImm * CopyScale; |
311 | 313 | |
312 | 313 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(CopyOpc), DestReg); |
313 | 313 | if (CopyNeedsCC) |
314 | 38 | MIB = MIB.add(t1CondCodeOp()); |
315 | 313 | MIB.addReg(BaseReg, RegState::Kill); |
316 | 313 | if (CopyOpc != ARM::tMOVr313 ) { |
317 | 264 | MIB.addImm(CopyImm); |
318 | 264 | } |
319 | 313 | MIB.setMIFlags(MIFlags).add(predOps(ARMCC::AL)); |
320 | 313 | |
321 | 313 | BaseReg = DestReg; |
322 | 313 | } |
323 | 1.38k | |
324 | 1.38k | // Emit zero or more in-place add/sub instructions |
325 | 2.28k | while (Bytes2.28k ) { |
326 | 897 | unsigned ExtraImm = std::min(Bytes, ExtraRange) / ExtraScale; |
327 | 897 | Bytes -= ExtraImm * ExtraScale; |
328 | 897 | |
329 | 897 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ExtraOpc), DestReg); |
330 | 897 | if (ExtraNeedsCC) |
331 | 46 | MIB = MIB.add(t1CondCodeOp()); |
332 | 897 | MIB.addReg(BaseReg) |
333 | 897 | .addImm(ExtraImm) |
334 | 897 | .add(predOps(ARMCC::AL)) |
335 | 897 | .setMIFlags(MIFlags); |
336 | 897 | } |
337 | 1.44k | } |
338 | | |
339 | 24 | static void removeOperands(MachineInstr &MI, unsigned i) { |
340 | 24 | unsigned Op = i; |
341 | 72 | for (unsigned e = MI.getNumOperands(); i != e72 ; ++i48 ) |
342 | 48 | MI.RemoveOperand(Op); |
343 | 24 | } |
344 | | |
345 | | /// convertToNonSPOpcode - Change the opcode to the non-SP version, because |
346 | | /// we're replacing the frame index with a non-SP register. |
347 | 3.56k | static unsigned convertToNonSPOpcode(unsigned Opcode) { |
348 | 3.56k | switch (Opcode) { |
349 | 2.32k | case ARM::tLDRspi: |
350 | 2.32k | return ARM::tLDRi; |
351 | 3.56k | |
352 | 1.23k | case ARM::tSTRspi: |
353 | 1.23k | return ARM::tSTRi; |
354 | 0 | } |
355 | 0 |
|
356 | 0 | return Opcode; |
357 | 0 | } |
358 | | |
359 | | bool ThumbRegisterInfo::rewriteFrameIndex(MachineBasicBlock::iterator II, |
360 | | unsigned FrameRegIdx, |
361 | | unsigned FrameReg, int &Offset, |
362 | 3.86k | const ARMBaseInstrInfo &TII) const { |
363 | 3.86k | MachineInstr &MI = *II; |
364 | 3.86k | MachineBasicBlock &MBB = *MI.getParent(); |
365 | 3.86k | assert(MBB.getParent()->getSubtarget<ARMSubtarget>().isThumb1Only() && |
366 | 3.86k | "This isn't needed for thumb2!"); |
367 | 3.86k | DebugLoc dl = MI.getDebugLoc(); |
368 | 3.86k | MachineInstrBuilder MIB(*MBB.getParent(), &MI); |
369 | 3.86k | unsigned Opcode = MI.getOpcode(); |
370 | 3.86k | const MCInstrDesc &Desc = MI.getDesc(); |
371 | 3.86k | unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); |
372 | 3.86k | |
373 | 3.86k | if (Opcode == ARM::tADDframe3.86k ) { |
374 | 278 | Offset += MI.getOperand(FrameRegIdx+1).getImm(); |
375 | 278 | unsigned DestReg = MI.getOperand(0).getReg(); |
376 | 278 | |
377 | 278 | emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII, |
378 | 278 | *this); |
379 | 278 | MBB.erase(II); |
380 | 278 | return true; |
381 | 0 | } else { |
382 | 3.58k | if (AddrMode != ARMII::AddrModeT1_s) |
383 | 0 | llvm_unreachable("Unsupported addressing mode!"); |
384 | 3.58k | |
385 | 3.58k | unsigned ImmIdx = FrameRegIdx + 1; |
386 | 3.58k | int InstrOffs = MI.getOperand(ImmIdx).getImm(); |
387 | 3.58k | unsigned NumBits = (FrameReg == ARM::SP) ? 83.55k : 535 ; |
388 | 3.58k | unsigned Scale = 4; |
389 | 3.58k | |
390 | 3.58k | Offset += InstrOffs * Scale; |
391 | 3.58k | assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!"); |
392 | 3.58k | |
393 | 3.58k | // Common case: small offset, fits into instruction. |
394 | 3.58k | MachineOperand &ImmOp = MI.getOperand(ImmIdx); |
395 | 3.58k | int ImmedOffset = Offset / Scale; |
396 | 3.58k | unsigned Mask = (1 << NumBits) - 1; |
397 | 3.58k | |
398 | 3.58k | if ((unsigned)Offset <= Mask * Scale3.58k ) { |
399 | 3.56k | // Replace the FrameIndex with the frame register (e.g., sp). |
400 | 3.56k | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
401 | 3.56k | ImmOp.ChangeToImmediate(ImmedOffset); |
402 | 3.56k | |
403 | 3.56k | // If we're using a register where sp was stored, convert the instruction |
404 | 3.56k | // to the non-SP version. |
405 | 3.56k | unsigned NewOpc = convertToNonSPOpcode(Opcode); |
406 | 3.56k | if (NewOpc != Opcode && 3.56k FrameReg != ARM::SP3.56k ) |
407 | 35 | MI.setDesc(TII.get(NewOpc)); |
408 | 3.56k | |
409 | 3.56k | return true; |
410 | 3.56k | } |
411 | 24 | |
412 | 24 | NumBits = 5; |
413 | 24 | Mask = (1 << NumBits) - 1; |
414 | 24 | |
415 | 24 | // If this is a thumb spill / restore, we will be using a constpool load to |
416 | 24 | // materialize the offset. |
417 | 24 | if (Opcode == ARM::tLDRspi || 24 Opcode == ARM::tSTRspi11 ) { |
418 | 24 | ImmOp.ChangeToImmediate(0); |
419 | 24 | } else { |
420 | 0 | // Otherwise, it didn't fit. Pull in what we can to simplify the immed. |
421 | 0 | ImmedOffset = ImmedOffset & Mask; |
422 | 0 | ImmOp.ChangeToImmediate(ImmedOffset); |
423 | 0 | Offset &= ~(Mask * Scale); |
424 | 0 | } |
425 | 3.58k | } |
426 | 3.86k | |
427 | 24 | return Offset == 0; |
428 | 3.86k | } |
429 | | |
430 | | void ThumbRegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, |
431 | 25 | int64_t Offset) const { |
432 | 25 | const MachineFunction &MF = *MI.getParent()->getParent(); |
433 | 25 | const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); |
434 | 25 | if (!STI.isThumb1Only()) |
435 | 15 | return ARMBaseRegisterInfo::resolveFrameIndex(MI, BaseReg, Offset); |
436 | 10 | |
437 | 10 | const ARMBaseInstrInfo &TII = *STI.getInstrInfo(); |
438 | 10 | int Off = Offset; // ARM doesn't need the general 64-bit offsets |
439 | 10 | unsigned i = 0; |
440 | 10 | |
441 | 20 | while (!MI.getOperand(i).isFI()20 ) { |
442 | 10 | ++i; |
443 | 10 | assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); |
444 | 10 | } |
445 | 25 | bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII); |
446 | 25 | assert (Done && "Unable to resolve frame index!"); |
447 | 25 | (void)Done; |
448 | 25 | } |
449 | | |
450 | | /// saveScavengerRegister - Spill the register so it can be used by the |
451 | | /// register scavenger. Return true. |
452 | | bool ThumbRegisterInfo::saveScavengerRegister( |
453 | | MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
454 | | MachineBasicBlock::iterator &UseMI, const TargetRegisterClass *RC, |
455 | 3 | unsigned Reg) const { |
456 | 3 | |
457 | 3 | const ARMSubtarget &STI = MBB.getParent()->getSubtarget<ARMSubtarget>(); |
458 | 3 | if (!STI.isThumb1Only()) |
459 | 1 | return ARMBaseRegisterInfo::saveScavengerRegister(MBB, I, UseMI, RC, Reg); |
460 | 2 | |
461 | 2 | // Thumb1 can't use the emergency spill slot on the stack because |
462 | 2 | // ldr/str immediate offsets must be positive, and if we're referencing |
463 | 2 | // off the frame pointer (if, for example, there are alloca() calls in |
464 | 2 | // the function, the offset will be negative. Use R12 instead since that's |
465 | 2 | // a call clobbered register that we know won't be used in Thumb1 mode. |
466 | 2 | const TargetInstrInfo &TII = *STI.getInstrInfo(); |
467 | 2 | DebugLoc DL; |
468 | 2 | BuildMI(MBB, I, DL, TII.get(ARM::tMOVr)) |
469 | 2 | .addReg(ARM::R12, RegState::Define) |
470 | 2 | .addReg(Reg, RegState::Kill) |
471 | 2 | .add(predOps(ARMCC::AL)); |
472 | 2 | |
473 | 2 | // The UseMI is where we would like to restore the register. If there's |
474 | 2 | // interference with R12 before then, however, we'll need to restore it |
475 | 2 | // before that instead and adjust the UseMI. |
476 | 2 | bool done = false; |
477 | 26 | for (MachineBasicBlock::iterator II = I; !done && 26 II != UseMI26 ; ++II24 ) { |
478 | 24 | if (II->isDebugValue()) |
479 | 0 | continue; |
480 | 24 | // If this instruction affects R12, adjust our restore point. |
481 | 112 | for (unsigned i = 0, e = II->getNumOperands(); 24 i != e112 ; ++i88 ) { |
482 | 88 | const MachineOperand &MO = II->getOperand(i); |
483 | 88 | if (MO.isRegMask() && 88 MO.clobbersPhysReg(ARM::R12)0 ) { |
484 | 0 | UseMI = II; |
485 | 0 | done = true; |
486 | 0 | break; |
487 | 0 | } |
488 | 88 | if (88 !MO.isReg() || 88 MO.isUndef()64 || !MO.getReg()64 || |
489 | 48 | TargetRegisterInfo::isVirtualRegister(MO.getReg())) |
490 | 72 | continue; |
491 | 16 | if (16 MO.getReg() == ARM::R1216 ) { |
492 | 0 | UseMI = II; |
493 | 0 | done = true; |
494 | 0 | break; |
495 | 0 | } |
496 | 88 | } |
497 | 24 | } |
498 | 3 | // Restore the register from R12 |
499 | 3 | BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)) |
500 | 3 | .addReg(Reg, RegState::Define) |
501 | 3 | .addReg(ARM::R12, RegState::Kill) |
502 | 3 | .add(predOps(ARMCC::AL)); |
503 | 3 | |
504 | 3 | return true; |
505 | 3 | } |
506 | | |
507 | | void ThumbRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, |
508 | | int SPAdj, unsigned FIOperandNum, |
509 | 18.9k | RegScavenger *RS) const { |
510 | 18.9k | MachineInstr &MI = *II; |
511 | 18.9k | MachineBasicBlock &MBB = *MI.getParent(); |
512 | 18.9k | MachineFunction &MF = *MBB.getParent(); |
513 | 18.9k | const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); |
514 | 18.9k | if (!STI.isThumb1Only()) |
515 | 15.1k | return ARMBaseRegisterInfo::eliminateFrameIndex(II, SPAdj, FIOperandNum, |
516 | 15.1k | RS); |
517 | 3.85k | |
518 | 3.85k | unsigned VReg = 0; |
519 | 3.85k | const ARMBaseInstrInfo &TII = *STI.getInstrInfo(); |
520 | 3.85k | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); |
521 | 3.85k | DebugLoc dl = MI.getDebugLoc(); |
522 | 3.85k | MachineInstrBuilder MIB(*MBB.getParent(), &MI); |
523 | 3.85k | |
524 | 3.85k | unsigned FrameReg = ARM::SP; |
525 | 3.85k | int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); |
526 | 3.85k | int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) + |
527 | 3.85k | MF.getFrameInfo().getStackSize() + SPAdj; |
528 | 3.85k | |
529 | 3.85k | if (MF.getFrameInfo().hasVarSizedObjects()3.85k ) { |
530 | 28 | assert(SPAdj == 0 && STI.getFrameLowering()->hasFP(MF) && "Unexpected"); |
531 | 28 | // There are alloca()'s in this function, must reference off the frame |
532 | 28 | // pointer or base pointer instead. |
533 | 28 | if (!hasBasePointer(MF)28 ) { |
534 | 0 | FrameReg = getFrameRegister(MF); |
535 | 0 | Offset -= AFI->getFramePtrSpillOffset(); |
536 | 0 | } else |
537 | 28 | FrameReg = BasePtr; |
538 | 28 | } |
539 | 3.85k | |
540 | 3.85k | // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the |
541 | 3.85k | // call frame setup/destroy instructions have already been eliminated. That |
542 | 3.85k | // means the stack pointer cannot be used to access the emergency spill slot |
543 | 3.85k | // when !hasReservedCallFrame(). |
544 | | #ifndef NDEBUG |
545 | | if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){ |
546 | | assert(STI.getFrameLowering()->hasReservedCallFrame(MF) && |
547 | | "Cannot use SP to access the emergency spill slot in " |
548 | | "functions without a reserved call frame"); |
549 | | assert(!MF.getFrameInfo().hasVarSizedObjects() && |
550 | | "Cannot use SP to access the emergency spill slot in " |
551 | | "functions with variable sized frame objects"); |
552 | | } |
553 | | #endif // NDEBUG |
554 | | |
555 | 3.85k | // Special handling of dbg_value instructions. |
556 | 3.85k | if (MI.isDebugValue()3.85k ) { |
557 | 0 | MI.getOperand(FIOperandNum). ChangeToRegister(FrameReg, false /*isDef*/); |
558 | 0 | MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); |
559 | 0 | return; |
560 | 0 | } |
561 | 3.85k | |
562 | 3.85k | // Modify MI as necessary to handle as much of 'Offset' as possible |
563 | 3.85k | assert(AFI->isThumbFunction() && |
564 | 3.85k | "This eliminateFrameIndex only supports Thumb1!"); |
565 | 3.85k | if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII)) |
566 | 3.83k | return; |
567 | 24 | |
568 | 24 | // If we get here, the immediate doesn't fit into the instruction. We folded |
569 | 24 | // as much as possible above, handle the rest, providing a register that is |
570 | 24 | // SP+LargeImm. |
571 | 3.85k | assert(Offset && "This code isn't needed if offset already handled!"); |
572 | 24 | |
573 | 24 | unsigned Opcode = MI.getOpcode(); |
574 | 24 | |
575 | 24 | // Remove predicate first. |
576 | 24 | int PIdx = MI.findFirstPredOperandIdx(); |
577 | 24 | if (PIdx != -1) |
578 | 24 | removeOperands(MI, PIdx); |
579 | 24 | |
580 | 24 | if (MI.mayLoad()24 ) { |
581 | 13 | // Use the destination register to materialize sp + offset. |
582 | 13 | unsigned TmpReg = MI.getOperand(0).getReg(); |
583 | 13 | bool UseRR = false; |
584 | 13 | if (Opcode == ARM::tLDRspi13 ) { |
585 | 13 | if (FrameReg == ARM::SP || 13 STI.genExecuteOnly()0 ) |
586 | 13 | emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, |
587 | 13 | Offset, false, TII, *this); |
588 | 0 | else { |
589 | 0 | emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); |
590 | 0 | UseRR = true; |
591 | 0 | } |
592 | 0 | } else { |
593 | 0 | emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII, |
594 | 0 | *this); |
595 | 0 | } |
596 | 13 | |
597 | 13 | MI.setDesc(TII.get(UseRR ? ARM::tLDRr0 : ARM::tLDRi13 )); |
598 | 13 | MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true); |
599 | 13 | if (UseRR) |
600 | 13 | // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame |
601 | 13 | // register. The offset is already handled in the vreg value. |
602 | 0 | MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, |
603 | 0 | false); |
604 | 24 | } else if (11 MI.mayStore()11 ) { |
605 | 11 | VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); |
606 | 11 | bool UseRR = false; |
607 | 11 | |
608 | 11 | if (Opcode == ARM::tSTRspi11 ) { |
609 | 11 | if (FrameReg == ARM::SP || 11 STI.genExecuteOnly()0 ) |
610 | 11 | emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, |
611 | 11 | Offset, false, TII, *this); |
612 | 0 | else { |
613 | 0 | emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); |
614 | 0 | UseRR = true; |
615 | 0 | } |
616 | 11 | } else |
617 | 0 | emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII, |
618 | 0 | *this); |
619 | 11 | MI.setDesc(TII.get(UseRR ? ARM::tSTRr0 : ARM::tSTRi11 )); |
620 | 11 | MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true); |
621 | 11 | if (UseRR) |
622 | 11 | // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame |
623 | 11 | // register. The offset is already handled in the vreg value. |
624 | 0 | MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, |
625 | 0 | false); |
626 | 0 | } else { |
627 | 0 | llvm_unreachable("Unexpected opcode!"); |
628 | 11 | } |
629 | 24 | |
630 | 24 | // Add predicate back if it's needed. |
631 | 24 | if (24 MI.isPredicable()24 ) |
632 | 24 | MIB.add(predOps(ARMCC::AL)); |
633 | 18.9k | } |