File: | lib/Target/ARM/Thumb1RegisterInfo.cpp |
Location: | line 208, column 5 |
Description: | Value stored to 'NumBits' is never read |
1 | //===-- Thumb1RegisterInfo.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 "Thumb1RegisterInfo.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 | Thumb1RegisterInfo::Thumb1RegisterInfo(const ARMSubtarget &sti) |
42 | : ARMBaseRegisterInfo(sti) { |
43 | } |
44 | |
45 | const TargetRegisterClass* |
46 | Thumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) |
47 | const { |
48 | if (ARM::tGPRRegClass.hasSubClassEq(RC)) |
49 | return &ARM::tGPRRegClass; |
50 | return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC); |
51 | } |
52 | |
53 | const TargetRegisterClass * |
54 | Thumb1RegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) |
55 | const { |
56 | return &ARM::tGPRRegClass; |
57 | } |
58 | |
59 | /// emitLoadConstPool - Emits a load from constpool to materialize the |
60 | /// specified immediate. |
61 | void |
62 | Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB, |
63 | MachineBasicBlock::iterator &MBBI, |
64 | DebugLoc dl, |
65 | unsigned DestReg, unsigned SubIdx, |
66 | int Val, |
67 | ARMCC::CondCodes Pred, unsigned PredReg, |
68 | unsigned MIFlags) const { |
69 | MachineFunction &MF = *MBB.getParent(); |
70 | const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); |
71 | MachineConstantPool *ConstantPool = MF.getConstantPool(); |
72 | const Constant *C = ConstantInt::get( |
73 | Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val); |
74 | unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); |
75 | |
76 | BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci)) |
77 | .addReg(DestReg, getDefRegState(true), SubIdx) |
78 | .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg) |
79 | .setMIFlags(MIFlags); |
80 | } |
81 | |
82 | |
83 | /// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize |
84 | /// a destreg = basereg + immediate in Thumb code. Materialize the immediate |
85 | /// in a register using mov / mvn sequences or load the immediate from a |
86 | /// constpool entry. |
87 | static |
88 | void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, |
89 | MachineBasicBlock::iterator &MBBI, |
90 | DebugLoc dl, |
91 | unsigned DestReg, unsigned BaseReg, |
92 | int NumBytes, bool CanChangeCC, |
93 | const TargetInstrInfo &TII, |
94 | const ARMBaseRegisterInfo& MRI, |
95 | unsigned MIFlags = MachineInstr::NoFlags) { |
96 | MachineFunction &MF = *MBB.getParent(); |
97 | bool isHigh = !isARMLowRegister(DestReg) || |
98 | (BaseReg != 0 && !isARMLowRegister(BaseReg)); |
99 | bool isSub = false; |
100 | // Subtract doesn't have high register version. Load the negative value |
101 | // if either base or dest register is a high register. Also, if do not |
102 | // issue sub as part of the sequence if condition register is to be |
103 | // preserved. |
104 | if (NumBytes < 0 && !isHigh && CanChangeCC) { |
105 | isSub = true; |
106 | NumBytes = -NumBytes; |
107 | } |
108 | unsigned LdReg = DestReg; |
109 | if (DestReg == ARM::SP) { |
110 | assert(BaseReg == ARM::SP && "Unexpected!")((BaseReg == ARM::SP && "Unexpected!") ? static_cast< void> (0) : __assert_fail ("BaseReg == ARM::SP && \"Unexpected!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 110, __PRETTY_FUNCTION__)); |
111 | LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); |
112 | } |
113 | |
114 | if (NumBytes <= 255 && NumBytes >= 0) |
115 | AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) |
116 | .addImm(NumBytes).setMIFlags(MIFlags); |
117 | else if (NumBytes < 0 && NumBytes >= -255) { |
118 | AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)) |
119 | .addImm(NumBytes).setMIFlags(MIFlags); |
120 | AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)) |
121 | .addReg(LdReg, RegState::Kill).setMIFlags(MIFlags); |
122 | } else |
123 | MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, |
124 | ARMCC::AL, 0, MIFlags); |
125 | |
126 | // Emit add / sub. |
127 | int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr); |
128 | MachineInstrBuilder MIB = |
129 | BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); |
130 | if (Opc != ARM::tADDhirr) |
131 | MIB = AddDefaultT1CC(MIB); |
132 | if (DestReg == ARM::SP || isSub) |
133 | MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill); |
134 | else |
135 | MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill); |
136 | AddDefaultPred(MIB); |
137 | } |
138 | |
139 | /// calcNumMI - Returns the number of instructions required to materialize |
140 | /// the specific add / sub r, c instruction. |
141 | static unsigned calcNumMI(int Opc, int ExtraOpc, unsigned Bytes, |
142 | unsigned NumBits, unsigned Scale) { |
143 | unsigned NumMIs = 0; |
144 | unsigned Chunk = ((1 << NumBits) - 1) * Scale; |
145 | |
146 | if (Opc == ARM::tADDrSPi) { |
147 | unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; |
148 | Bytes -= ThisVal; |
149 | NumMIs++; |
150 | NumBits = 8; |
151 | Scale = 1; // Followed by a number of tADDi8. |
152 | Chunk = ((1 << NumBits) - 1) * Scale; |
153 | } |
154 | |
155 | NumMIs += Bytes / Chunk; |
156 | if ((Bytes % Chunk) != 0) |
157 | NumMIs++; |
158 | if (ExtraOpc) |
159 | NumMIs++; |
160 | return NumMIs; |
161 | } |
162 | |
163 | /// emitThumbRegPlusImmediate - Emits a series of instructions to materialize |
164 | /// a destreg = basereg + immediate in Thumb code. |
165 | void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB, |
166 | MachineBasicBlock::iterator &MBBI, |
167 | DebugLoc dl, |
168 | unsigned DestReg, unsigned BaseReg, |
169 | int NumBytes, const TargetInstrInfo &TII, |
170 | const ARMBaseRegisterInfo& MRI, |
171 | unsigned MIFlags) { |
172 | bool isSub = NumBytes < 0; |
173 | unsigned Bytes = (unsigned)NumBytes; |
174 | if (isSub) Bytes = -NumBytes; |
175 | bool isMul4 = (Bytes & 3) == 0; |
176 | bool isTwoAddr = false; |
177 | bool DstNotEqBase = false; |
178 | unsigned NumBits = 1; |
179 | unsigned Scale = 1; |
180 | int Opc = 0; |
181 | int ExtraOpc = 0; |
182 | bool NeedCC = false; |
183 | |
184 | if (DestReg == BaseReg && BaseReg == ARM::SP) { |
185 | assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!")((isMul4 && "Thumb sp inc / dec size must be multiple of 4!" ) ? static_cast<void> (0) : __assert_fail ("isMul4 && \"Thumb sp inc / dec size must be multiple of 4!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 185, __PRETTY_FUNCTION__)); |
186 | NumBits = 7; |
187 | Scale = 4; |
188 | Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; |
189 | isTwoAddr = true; |
190 | } else if (!isSub && BaseReg == ARM::SP) { |
191 | // r1 = add sp, 403 |
192 | // => |
193 | // r1 = add sp, 100 * 4 |
194 | // r1 = add r1, 3 |
195 | if (!isMul4) { |
196 | Bytes &= ~3; |
197 | ExtraOpc = ARM::tADDi3; |
198 | } |
199 | NumBits = 8; |
200 | Scale = 4; |
201 | Opc = ARM::tADDrSPi; |
202 | } else { |
203 | // sp = sub sp, c |
204 | // r1 = sub sp, c |
205 | // r8 = sub sp, c |
206 | if (DestReg != BaseReg) |
207 | DstNotEqBase = true; |
208 | NumBits = 8; |
Value stored to 'NumBits' is never read | |
209 | if (DestReg == ARM::SP) { |
210 | Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; |
211 | assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!")((isMul4 && "Thumb sp inc / dec size must be multiple of 4!" ) ? static_cast<void> (0) : __assert_fail ("isMul4 && \"Thumb sp inc / dec size must be multiple of 4!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 211, __PRETTY_FUNCTION__)); |
212 | NumBits = 7; |
213 | Scale = 4; |
214 | } else { |
215 | Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; |
216 | NumBits = 8; |
217 | NeedCC = true; |
218 | } |
219 | isTwoAddr = true; |
220 | } |
221 | |
222 | unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); |
223 | unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; |
224 | if (NumMIs > Threshold) { |
225 | // This will expand into too many instructions. Load the immediate from a |
226 | // constpool entry. |
227 | emitThumbRegPlusImmInReg(MBB, MBBI, dl, |
228 | DestReg, BaseReg, NumBytes, true, |
229 | TII, MRI, MIFlags); |
230 | return; |
231 | } |
232 | |
233 | if (DstNotEqBase) { |
234 | if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { |
235 | // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) |
236 | unsigned Chunk = (1 << 3) - 1; |
237 | unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; |
238 | Bytes -= ThisVal; |
239 | const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); |
240 | const MachineInstrBuilder MIB = |
241 | AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg) |
242 | .setMIFlags(MIFlags)); |
243 | AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); |
244 | } else { |
245 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) |
246 | .addReg(BaseReg, RegState::Kill)) |
247 | .setMIFlags(MIFlags); |
248 | } |
249 | BaseReg = DestReg; |
250 | } |
251 | |
252 | unsigned Chunk = ((1 << NumBits) - 1) * Scale; |
253 | while (Bytes) { |
254 | unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; |
255 | Bytes -= ThisVal; |
256 | ThisVal /= Scale; |
257 | // Build the new tADD / tSUB. |
258 | if (isTwoAddr) { |
259 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); |
260 | if (NeedCC) |
261 | MIB = AddDefaultT1CC(MIB); |
262 | MIB.addReg(DestReg).addImm(ThisVal); |
263 | MIB = AddDefaultPred(MIB); |
264 | MIB.setMIFlags(MIFlags); |
265 | } else { |
266 | bool isKill = BaseReg != ARM::SP; |
267 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); |
268 | if (NeedCC) |
269 | MIB = AddDefaultT1CC(MIB); |
270 | MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); |
271 | MIB = AddDefaultPred(MIB); |
272 | MIB.setMIFlags(MIFlags); |
273 | |
274 | BaseReg = DestReg; |
275 | if (Opc == ARM::tADDrSPi) { |
276 | // r4 = add sp, imm |
277 | // r4 = add r4, imm |
278 | // ... |
279 | NumBits = 8; |
280 | Scale = 1; |
281 | Chunk = ((1 << NumBits) - 1) * Scale; |
282 | Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; |
283 | NeedCC = isTwoAddr = true; |
284 | } |
285 | } |
286 | } |
287 | |
288 | if (ExtraOpc) { |
289 | const MCInstrDesc &MCID = TII.get(ExtraOpc); |
290 | AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) |
291 | .addReg(DestReg, RegState::Kill) |
292 | .addImm(((unsigned)NumBytes) & 3) |
293 | .setMIFlags(MIFlags)); |
294 | } |
295 | } |
296 | |
297 | /// emitThumbConstant - Emit a series of instructions to materialize a |
298 | /// constant. |
299 | static void emitThumbConstant(MachineBasicBlock &MBB, |
300 | MachineBasicBlock::iterator &MBBI, |
301 | unsigned DestReg, int Imm, |
302 | const TargetInstrInfo &TII, |
303 | const Thumb1RegisterInfo& MRI, |
304 | DebugLoc dl) { |
305 | bool isSub = Imm < 0; |
306 | if (isSub) Imm = -Imm; |
307 | |
308 | int Chunk = (1 << 8) - 1; |
309 | int ThisVal = (Imm > Chunk) ? Chunk : Imm; |
310 | Imm -= ThisVal; |
311 | AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), |
312 | DestReg)) |
313 | .addImm(ThisVal)); |
314 | if (Imm > 0) |
315 | emitThumbRegPlusImmediate(MBB, MBBI, dl, DestReg, DestReg, Imm, TII, MRI); |
316 | if (isSub) { |
317 | const MCInstrDesc &MCID = TII.get(ARM::tRSB); |
318 | AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) |
319 | .addReg(DestReg, RegState::Kill)); |
320 | } |
321 | } |
322 | |
323 | static void removeOperands(MachineInstr &MI, unsigned i) { |
324 | unsigned Op = i; |
325 | for (unsigned e = MI.getNumOperands(); i != e; ++i) |
326 | MI.RemoveOperand(Op); |
327 | } |
328 | |
329 | /// convertToNonSPOpcode - Change the opcode to the non-SP version, because |
330 | /// we're replacing the frame index with a non-SP register. |
331 | static unsigned convertToNonSPOpcode(unsigned Opcode) { |
332 | switch (Opcode) { |
333 | case ARM::tLDRspi: |
334 | return ARM::tLDRi; |
335 | |
336 | case ARM::tSTRspi: |
337 | return ARM::tSTRi; |
338 | } |
339 | |
340 | return Opcode; |
341 | } |
342 | |
343 | bool Thumb1RegisterInfo:: |
344 | rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, |
345 | unsigned FrameReg, int &Offset, |
346 | const ARMBaseInstrInfo &TII) const { |
347 | MachineInstr &MI = *II; |
348 | MachineBasicBlock &MBB = *MI.getParent(); |
349 | DebugLoc dl = MI.getDebugLoc(); |
350 | MachineInstrBuilder MIB(*MBB.getParent(), &MI); |
351 | unsigned Opcode = MI.getOpcode(); |
352 | const MCInstrDesc &Desc = MI.getDesc(); |
353 | unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); |
354 | |
355 | if (Opcode == ARM::tADDrSPi) { |
356 | Offset += MI.getOperand(FrameRegIdx+1).getImm(); |
357 | |
358 | // Can't use tADDrSPi if it's based off the frame pointer. |
359 | unsigned NumBits = 0; |
360 | unsigned Scale = 1; |
361 | if (FrameReg != ARM::SP) { |
362 | Opcode = ARM::tADDi3; |
363 | NumBits = 3; |
364 | } else { |
365 | NumBits = 8; |
366 | Scale = 4; |
367 | assert((Offset & 3) == 0 &&(((Offset & 3) == 0 && "Thumb add/sub sp, #imm immediate must be multiple of 4!" ) ? static_cast<void> (0) : __assert_fail ("(Offset & 3) == 0 && \"Thumb add/sub sp, #imm immediate must be multiple of 4!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 368, __PRETTY_FUNCTION__)) |
368 | "Thumb add/sub sp, #imm immediate must be multiple of 4!")(((Offset & 3) == 0 && "Thumb add/sub sp, #imm immediate must be multiple of 4!" ) ? static_cast<void> (0) : __assert_fail ("(Offset & 3) == 0 && \"Thumb add/sub sp, #imm immediate must be multiple of 4!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 368, __PRETTY_FUNCTION__)); |
369 | } |
370 | |
371 | unsigned PredReg; |
372 | if (Offset == 0 && getInstrPredicate(&MI, PredReg) == ARMCC::AL) { |
373 | // Turn it into a move. |
374 | MI.setDesc(TII.get(ARM::tMOVr)); |
375 | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
376 | // Remove offset |
377 | MI.RemoveOperand(FrameRegIdx+1); |
378 | return true; |
379 | } |
380 | |
381 | // Common case: small offset, fits into instruction. |
382 | unsigned Mask = (1 << NumBits) - 1; |
383 | if (((Offset / Scale) & ~Mask) == 0) { |
384 | // Replace the FrameIndex with sp / fp |
385 | if (Opcode == ARM::tADDi3) { |
386 | MI.setDesc(TII.get(Opcode)); |
387 | removeOperands(MI, FrameRegIdx); |
388 | AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg) |
389 | .addImm(Offset / Scale)); |
390 | } else { |
391 | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
392 | MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset / Scale); |
393 | } |
394 | return true; |
395 | } |
396 | |
397 | unsigned DestReg = MI.getOperand(0).getReg(); |
398 | unsigned Bytes = (Offset > 0) ? Offset : -Offset; |
399 | unsigned NumMIs = calcNumMI(Opcode, 0, Bytes, NumBits, Scale); |
400 | // MI would expand into a large number of instructions. Don't try to |
401 | // simplify the immediate. |
402 | if (NumMIs > 2) { |
403 | emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII, |
404 | *this); |
405 | MBB.erase(II); |
406 | return true; |
407 | } |
408 | |
409 | if (Offset > 0) { |
410 | // Translate r0 = add sp, imm to |
411 | // r0 = add sp, 255*4 |
412 | // r0 = add r0, (imm - 255*4) |
413 | if (Opcode == ARM::tADDi3) { |
414 | MI.setDesc(TII.get(Opcode)); |
415 | removeOperands(MI, FrameRegIdx); |
416 | AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg).addImm(Mask)); |
417 | } else { |
418 | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
419 | MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Mask); |
420 | } |
421 | Offset = (Offset - Mask * Scale); |
422 | MachineBasicBlock::iterator NII = std::next(II); |
423 | emitThumbRegPlusImmediate(MBB, NII, dl, DestReg, DestReg, Offset, TII, |
424 | *this); |
425 | } else { |
426 | // Translate r0 = add sp, -imm to |
427 | // r0 = -imm (this is then translated into a series of instructions) |
428 | // r0 = add r0, sp |
429 | emitThumbConstant(MBB, II, DestReg, Offset, TII, *this, dl); |
430 | |
431 | MI.setDesc(TII.get(ARM::tADDhirr)); |
432 | MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true); |
433 | MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false); |
434 | } |
435 | return true; |
436 | } else { |
437 | if (AddrMode != ARMII::AddrModeT1_s) |
438 | llvm_unreachable("Unsupported addressing mode!")::llvm::llvm_unreachable_internal("Unsupported addressing mode!" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 438); |
439 | |
440 | unsigned ImmIdx = FrameRegIdx + 1; |
441 | int InstrOffs = MI.getOperand(ImmIdx).getImm(); |
442 | unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5; |
443 | unsigned Scale = 4; |
444 | |
445 | Offset += InstrOffs * Scale; |
446 | assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!")(((Offset & (Scale - 1)) == 0 && "Can't encode this offset!" ) ? static_cast<void> (0) : __assert_fail ("(Offset & (Scale - 1)) == 0 && \"Can't encode this offset!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 446, __PRETTY_FUNCTION__)); |
447 | |
448 | // Common case: small offset, fits into instruction. |
449 | MachineOperand &ImmOp = MI.getOperand(ImmIdx); |
450 | int ImmedOffset = Offset / Scale; |
451 | unsigned Mask = (1 << NumBits) - 1; |
452 | |
453 | if ((unsigned)Offset <= Mask * Scale) { |
454 | // Replace the FrameIndex with the frame register (e.g., sp). |
455 | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
456 | ImmOp.ChangeToImmediate(ImmedOffset); |
457 | |
458 | // If we're using a register where sp was stored, convert the instruction |
459 | // to the non-SP version. |
460 | unsigned NewOpc = convertToNonSPOpcode(Opcode); |
461 | if (NewOpc != Opcode && FrameReg != ARM::SP) |
462 | MI.setDesc(TII.get(NewOpc)); |
463 | |
464 | return true; |
465 | } |
466 | |
467 | NumBits = 5; |
468 | Mask = (1 << NumBits) - 1; |
469 | |
470 | // If this is a thumb spill / restore, we will be using a constpool load to |
471 | // materialize the offset. |
472 | if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) { |
473 | ImmOp.ChangeToImmediate(0); |
474 | } else { |
475 | // Otherwise, it didn't fit. Pull in what we can to simplify the immed. |
476 | ImmedOffset = ImmedOffset & Mask; |
477 | ImmOp.ChangeToImmediate(ImmedOffset); |
478 | Offset &= ~(Mask * Scale); |
479 | } |
480 | } |
481 | |
482 | return Offset == 0; |
483 | } |
484 | |
485 | void Thumb1RegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, |
486 | int64_t Offset) const { |
487 | const ARMBaseInstrInfo &TII = |
488 | *static_cast<const ARMBaseInstrInfo *>(MI.getParent() |
489 | ->getParent() |
490 | ->getTarget() |
491 | .getSubtargetImpl() |
492 | ->getInstrInfo()); |
493 | int Off = Offset; // ARM doesn't need the general 64-bit offsets |
494 | unsigned i = 0; |
495 | |
496 | while (!MI.getOperand(i).isFI()) { |
497 | ++i; |
498 | assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!")((i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!" ) ? static_cast<void> (0) : __assert_fail ("i < MI.getNumOperands() && \"Instr doesn't have FrameIndex operand!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 498, __PRETTY_FUNCTION__)); |
499 | } |
500 | bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII); |
501 | assert (Done && "Unable to resolve frame index!")((Done && "Unable to resolve frame index!") ? static_cast <void> (0) : __assert_fail ("Done && \"Unable to resolve frame index!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 501, __PRETTY_FUNCTION__)); |
502 | (void)Done; |
503 | } |
504 | |
505 | /// saveScavengerRegister - Spill the register so it can be used by the |
506 | /// register scavenger. Return true. |
507 | bool |
508 | Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, |
509 | MachineBasicBlock::iterator I, |
510 | MachineBasicBlock::iterator &UseMI, |
511 | const TargetRegisterClass *RC, |
512 | unsigned Reg) const { |
513 | // Thumb1 can't use the emergency spill slot on the stack because |
514 | // ldr/str immediate offsets must be positive, and if we're referencing |
515 | // off the frame pointer (if, for example, there are alloca() calls in |
516 | // the function, the offset will be negative. Use R12 instead since that's |
517 | // a call clobbered register that we know won't be used in Thumb1 mode. |
518 | const TargetInstrInfo &TII = *MBB.getParent()->getSubtarget().getInstrInfo(); |
519 | DebugLoc DL; |
520 | AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr)) |
521 | .addReg(ARM::R12, RegState::Define) |
522 | .addReg(Reg, RegState::Kill)); |
523 | |
524 | // The UseMI is where we would like to restore the register. If there's |
525 | // interference with R12 before then, however, we'll need to restore it |
526 | // before that instead and adjust the UseMI. |
527 | bool done = false; |
528 | for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { |
529 | if (II->isDebugValue()) |
530 | continue; |
531 | // If this instruction affects R12, adjust our restore point. |
532 | for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { |
533 | const MachineOperand &MO = II->getOperand(i); |
534 | if (MO.isRegMask() && MO.clobbersPhysReg(ARM::R12)) { |
535 | UseMI = II; |
536 | done = true; |
537 | break; |
538 | } |
539 | if (!MO.isReg() || MO.isUndef() || !MO.getReg() || |
540 | TargetRegisterInfo::isVirtualRegister(MO.getReg())) |
541 | continue; |
542 | if (MO.getReg() == ARM::R12) { |
543 | UseMI = II; |
544 | done = true; |
545 | break; |
546 | } |
547 | } |
548 | } |
549 | // Restore the register from R12 |
550 | AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)). |
551 | addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill)); |
552 | |
553 | return true; |
554 | } |
555 | |
556 | void |
557 | Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, |
558 | int SPAdj, unsigned FIOperandNum, |
559 | RegScavenger *RS) const { |
560 | unsigned VReg = 0; |
561 | MachineInstr &MI = *II; |
562 | MachineBasicBlock &MBB = *MI.getParent(); |
563 | MachineFunction &MF = *MBB.getParent(); |
564 | const ARMBaseInstrInfo &TII = |
565 | *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo()); |
566 | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); |
567 | DebugLoc dl = MI.getDebugLoc(); |
568 | MachineInstrBuilder MIB(*MBB.getParent(), &MI); |
569 | |
570 | unsigned FrameReg = ARM::SP; |
571 | int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); |
572 | int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + |
573 | MF.getFrameInfo()->getStackSize() + SPAdj; |
574 | |
575 | if (MF.getFrameInfo()->hasVarSizedObjects()) { |
576 | assert(SPAdj == 0 && MF.getSubtarget().getFrameLowering()->hasFP(MF) &&((SPAdj == 0 && MF.getSubtarget().getFrameLowering()-> hasFP(MF) && "Unexpected") ? static_cast<void> ( 0) : __assert_fail ("SPAdj == 0 && MF.getSubtarget().getFrameLowering()->hasFP(MF) && \"Unexpected\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 577, __PRETTY_FUNCTION__)) |
577 | "Unexpected")((SPAdj == 0 && MF.getSubtarget().getFrameLowering()-> hasFP(MF) && "Unexpected") ? static_cast<void> ( 0) : __assert_fail ("SPAdj == 0 && MF.getSubtarget().getFrameLowering()->hasFP(MF) && \"Unexpected\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 577, __PRETTY_FUNCTION__)); |
578 | // There are alloca()'s in this function, must reference off the frame |
579 | // pointer or base pointer instead. |
580 | if (!hasBasePointer(MF)) { |
581 | FrameReg = getFrameRegister(MF); |
582 | Offset -= AFI->getFramePtrSpillOffset(); |
583 | } else |
584 | FrameReg = BasePtr; |
585 | } |
586 | |
587 | // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the |
588 | // call frame setup/destroy instructions have already been eliminated. That |
589 | // means the stack pointer cannot be used to access the emergency spill slot |
590 | // when !hasReservedCallFrame(). |
591 | #ifndef NDEBUG |
592 | if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){ |
593 | assert(MF.getTarget()((MF.getTarget() .getSubtargetImpl() ->getFrameLowering() -> hasReservedCallFrame(MF) && "Cannot use SP to access the emergency spill slot in " "functions without a reserved call frame") ? static_cast< void> (0) : __assert_fail ("MF.getTarget() .getSubtargetImpl() ->getFrameLowering() ->hasReservedCallFrame(MF) && \"Cannot use SP to access the emergency spill slot in \" \"functions without a reserved call frame\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 598, __PRETTY_FUNCTION__)) |
594 | .getSubtargetImpl()((MF.getTarget() .getSubtargetImpl() ->getFrameLowering() -> hasReservedCallFrame(MF) && "Cannot use SP to access the emergency spill slot in " "functions without a reserved call frame") ? static_cast< void> (0) : __assert_fail ("MF.getTarget() .getSubtargetImpl() ->getFrameLowering() ->hasReservedCallFrame(MF) && \"Cannot use SP to access the emergency spill slot in \" \"functions without a reserved call frame\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 598, __PRETTY_FUNCTION__)) |
595 | ->getFrameLowering()((MF.getTarget() .getSubtargetImpl() ->getFrameLowering() -> hasReservedCallFrame(MF) && "Cannot use SP to access the emergency spill slot in " "functions without a reserved call frame") ? static_cast< void> (0) : __assert_fail ("MF.getTarget() .getSubtargetImpl() ->getFrameLowering() ->hasReservedCallFrame(MF) && \"Cannot use SP to access the emergency spill slot in \" \"functions without a reserved call frame\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 598, __PRETTY_FUNCTION__)) |
596 | ->hasReservedCallFrame(MF) &&((MF.getTarget() .getSubtargetImpl() ->getFrameLowering() -> hasReservedCallFrame(MF) && "Cannot use SP to access the emergency spill slot in " "functions without a reserved call frame") ? static_cast< void> (0) : __assert_fail ("MF.getTarget() .getSubtargetImpl() ->getFrameLowering() ->hasReservedCallFrame(MF) && \"Cannot use SP to access the emergency spill slot in \" \"functions without a reserved call frame\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 598, __PRETTY_FUNCTION__)) |
597 | "Cannot use SP to access the emergency spill slot in "((MF.getTarget() .getSubtargetImpl() ->getFrameLowering() -> hasReservedCallFrame(MF) && "Cannot use SP to access the emergency spill slot in " "functions without a reserved call frame") ? static_cast< void> (0) : __assert_fail ("MF.getTarget() .getSubtargetImpl() ->getFrameLowering() ->hasReservedCallFrame(MF) && \"Cannot use SP to access the emergency spill slot in \" \"functions without a reserved call frame\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 598, __PRETTY_FUNCTION__)) |
598 | "functions without a reserved call frame")((MF.getTarget() .getSubtargetImpl() ->getFrameLowering() -> hasReservedCallFrame(MF) && "Cannot use SP to access the emergency spill slot in " "functions without a reserved call frame") ? static_cast< void> (0) : __assert_fail ("MF.getTarget() .getSubtargetImpl() ->getFrameLowering() ->hasReservedCallFrame(MF) && \"Cannot use SP to access the emergency spill slot in \" \"functions without a reserved call frame\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 598, __PRETTY_FUNCTION__)); |
599 | assert(!MF.getFrameInfo()->hasVarSizedObjects() &&((!MF.getFrameInfo()->hasVarSizedObjects() && "Cannot use SP to access the emergency spill slot in " "functions with variable sized frame objects") ? static_cast <void> (0) : __assert_fail ("!MF.getFrameInfo()->hasVarSizedObjects() && \"Cannot use SP to access the emergency spill slot in \" \"functions with variable sized frame objects\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 601, __PRETTY_FUNCTION__)) |
600 | "Cannot use SP to access the emergency spill slot in "((!MF.getFrameInfo()->hasVarSizedObjects() && "Cannot use SP to access the emergency spill slot in " "functions with variable sized frame objects") ? static_cast <void> (0) : __assert_fail ("!MF.getFrameInfo()->hasVarSizedObjects() && \"Cannot use SP to access the emergency spill slot in \" \"functions with variable sized frame objects\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 601, __PRETTY_FUNCTION__)) |
601 | "functions with variable sized frame objects")((!MF.getFrameInfo()->hasVarSizedObjects() && "Cannot use SP to access the emergency spill slot in " "functions with variable sized frame objects") ? static_cast <void> (0) : __assert_fail ("!MF.getFrameInfo()->hasVarSizedObjects() && \"Cannot use SP to access the emergency spill slot in \" \"functions with variable sized frame objects\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 601, __PRETTY_FUNCTION__)); |
602 | } |
603 | #endif // NDEBUG |
604 | |
605 | // Special handling of dbg_value instructions. |
606 | if (MI.isDebugValue()) { |
607 | MI.getOperand(FIOperandNum). ChangeToRegister(FrameReg, false /*isDef*/); |
608 | MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); |
609 | return; |
610 | } |
611 | |
612 | // Modify MI as necessary to handle as much of 'Offset' as possible |
613 | assert(AFI->isThumbFunction() &&((AFI->isThumbFunction() && "This eliminateFrameIndex only supports Thumb1!" ) ? static_cast<void> (0) : __assert_fail ("AFI->isThumbFunction() && \"This eliminateFrameIndex only supports Thumb1!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 614, __PRETTY_FUNCTION__)) |
614 | "This eliminateFrameIndex only supports Thumb1!")((AFI->isThumbFunction() && "This eliminateFrameIndex only supports Thumb1!" ) ? static_cast<void> (0) : __assert_fail ("AFI->isThumbFunction() && \"This eliminateFrameIndex only supports Thumb1!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 614, __PRETTY_FUNCTION__)); |
615 | if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII)) |
616 | return; |
617 | |
618 | // If we get here, the immediate doesn't fit into the instruction. We folded |
619 | // as much as possible above, handle the rest, providing a register that is |
620 | // SP+LargeImm. |
621 | assert(Offset && "This code isn't needed if offset already handled!")((Offset && "This code isn't needed if offset already handled!" ) ? static_cast<void> (0) : __assert_fail ("Offset && \"This code isn't needed if offset already handled!\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 621, __PRETTY_FUNCTION__)); |
622 | |
623 | unsigned Opcode = MI.getOpcode(); |
624 | |
625 | // Remove predicate first. |
626 | int PIdx = MI.findFirstPredOperandIdx(); |
627 | if (PIdx != -1) |
628 | removeOperands(MI, PIdx); |
629 | |
630 | if (MI.mayLoad()) { |
631 | // Use the destination register to materialize sp + offset. |
632 | unsigned TmpReg = MI.getOperand(0).getReg(); |
633 | bool UseRR = false; |
634 | if (Opcode == ARM::tLDRspi) { |
635 | if (FrameReg == ARM::SP) |
636 | emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, |
637 | Offset, false, TII, *this); |
638 | else { |
639 | emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); |
640 | UseRR = true; |
641 | } |
642 | } else { |
643 | emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII, |
644 | *this); |
645 | } |
646 | |
647 | MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi)); |
648 | MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true); |
649 | if (UseRR) |
650 | // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame |
651 | // register. The offset is already handled in the vreg value. |
652 | MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, |
653 | false); |
654 | } else if (MI.mayStore()) { |
655 | VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); |
656 | bool UseRR = false; |
657 | |
658 | if (Opcode == ARM::tSTRspi) { |
659 | if (FrameReg == ARM::SP) |
660 | emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, |
661 | Offset, false, TII, *this); |
662 | else { |
663 | emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); |
664 | UseRR = true; |
665 | } |
666 | } else |
667 | emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII, |
668 | *this); |
669 | MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi)); |
670 | MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true); |
671 | if (UseRR) |
672 | // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame |
673 | // register. The offset is already handled in the vreg value. |
674 | MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, |
675 | false); |
676 | } else { |
677 | llvm_unreachable("Unexpected opcode!")::llvm::llvm_unreachable_internal("Unexpected opcode!", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn219601/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 677); |
678 | } |
679 | |
680 | // Add predicate back if it's needed. |
681 | if (MI.isPredicable()) |
682 | AddDefaultPred(MIB); |
683 | } |