File: | lib/Target/ARM/Thumb1RegisterInfo.cpp |
Location: | line 209, 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~svn220848/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~svn220848/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 | DstNotEqBase = true; |
200 | NumBits = 8; |
201 | Scale = 4; |
202 | Opc = ARM::tADDrSPi; |
203 | } else { |
204 | // sp = sub sp, c |
205 | // r1 = sub sp, c |
206 | // r8 = sub sp, c |
207 | if (DestReg != BaseReg) |
208 | DstNotEqBase = true; |
209 | NumBits = 8; |
Value stored to 'NumBits' is never read | |
210 | if (DestReg == ARM::SP) { |
211 | Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; |
212 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 212, __PRETTY_FUNCTION__)); |
213 | NumBits = 7; |
214 | Scale = 4; |
215 | } else { |
216 | Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; |
217 | NumBits = 8; |
218 | NeedCC = true; |
219 | } |
220 | isTwoAddr = true; |
221 | } |
222 | |
223 | unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale); |
224 | unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2; |
225 | if (NumMIs > Threshold) { |
226 | // This will expand into too many instructions. Load the immediate from a |
227 | // constpool entry. |
228 | emitThumbRegPlusImmInReg(MBB, MBBI, dl, |
229 | DestReg, BaseReg, NumBytes, true, |
230 | TII, MRI, MIFlags); |
231 | return; |
232 | } |
233 | |
234 | if (DstNotEqBase) { |
235 | if (isARMLowRegister(DestReg) && isARMLowRegister(BaseReg)) { |
236 | // If both are low registers, emit DestReg = add BaseReg, max(Imm, 7) |
237 | unsigned Chunk = (1 << 3) - 1; |
238 | unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; |
239 | Bytes -= ThisVal; |
240 | const MCInstrDesc &MCID = TII.get(isSub ? ARM::tSUBi3 : ARM::tADDi3); |
241 | const MachineInstrBuilder MIB = |
242 | AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg) |
243 | .setMIFlags(MIFlags)); |
244 | AddDefaultPred(MIB.addReg(BaseReg, RegState::Kill).addImm(ThisVal)); |
245 | } else if (isARMLowRegister(DestReg) && BaseReg == ARM::SP && Bytes > 0) { |
246 | unsigned ThisVal = std::min(1020U, Bytes / 4 * 4); |
247 | Bytes -= ThisVal; |
248 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), DestReg) |
249 | .addReg(BaseReg, RegState::Kill).addImm(ThisVal / 4)) |
250 | .setMIFlags(MIFlags); |
251 | } else { |
252 | AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) |
253 | .addReg(BaseReg, RegState::Kill)) |
254 | .setMIFlags(MIFlags); |
255 | } |
256 | BaseReg = DestReg; |
257 | } |
258 | |
259 | unsigned Chunk = ((1 << NumBits) - 1) * Scale; |
260 | while (Bytes) { |
261 | unsigned ThisVal = (Bytes > Chunk) ? Chunk : Bytes; |
262 | Bytes -= ThisVal; |
263 | ThisVal /= Scale; |
264 | // Build the new tADD / tSUB. |
265 | if (isTwoAddr) { |
266 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); |
267 | if (NeedCC) |
268 | MIB = AddDefaultT1CC(MIB); |
269 | MIB.addReg(DestReg).addImm(ThisVal); |
270 | MIB = AddDefaultPred(MIB); |
271 | MIB.setMIFlags(MIFlags); |
272 | } else { |
273 | bool isKill = BaseReg != ARM::SP; |
274 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg); |
275 | if (NeedCC) |
276 | MIB = AddDefaultT1CC(MIB); |
277 | MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal); |
278 | MIB = AddDefaultPred(MIB); |
279 | MIB.setMIFlags(MIFlags); |
280 | |
281 | BaseReg = DestReg; |
282 | if (Opc == ARM::tADDrSPi) { |
283 | // r4 = add sp, imm |
284 | // r4 = add r4, imm |
285 | // ... |
286 | NumBits = 8; |
287 | Scale = 1; |
288 | Chunk = ((1 << NumBits) - 1) * Scale; |
289 | Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8; |
290 | NeedCC = isTwoAddr = true; |
291 | } |
292 | } |
293 | } |
294 | |
295 | if (ExtraOpc) { |
296 | const MCInstrDesc &MCID = TII.get(ExtraOpc); |
297 | AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, MCID, DestReg)) |
298 | .addReg(DestReg, RegState::Kill) |
299 | .addImm(((unsigned)NumBytes) & 3) |
300 | .setMIFlags(MIFlags)); |
301 | } |
302 | } |
303 | |
304 | static void removeOperands(MachineInstr &MI, unsigned i) { |
305 | unsigned Op = i; |
306 | for (unsigned e = MI.getNumOperands(); i != e; ++i) |
307 | MI.RemoveOperand(Op); |
308 | } |
309 | |
310 | /// convertToNonSPOpcode - Change the opcode to the non-SP version, because |
311 | /// we're replacing the frame index with a non-SP register. |
312 | static unsigned convertToNonSPOpcode(unsigned Opcode) { |
313 | switch (Opcode) { |
314 | case ARM::tLDRspi: |
315 | return ARM::tLDRi; |
316 | |
317 | case ARM::tSTRspi: |
318 | return ARM::tSTRi; |
319 | } |
320 | |
321 | return Opcode; |
322 | } |
323 | |
324 | bool Thumb1RegisterInfo:: |
325 | rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, |
326 | unsigned FrameReg, int &Offset, |
327 | const ARMBaseInstrInfo &TII) const { |
328 | MachineInstr &MI = *II; |
329 | MachineBasicBlock &MBB = *MI.getParent(); |
330 | DebugLoc dl = MI.getDebugLoc(); |
331 | MachineInstrBuilder MIB(*MBB.getParent(), &MI); |
332 | unsigned Opcode = MI.getOpcode(); |
333 | const MCInstrDesc &Desc = MI.getDesc(); |
334 | unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); |
335 | |
336 | if (Opcode == ARM::tADDframe) { |
337 | Offset += MI.getOperand(FrameRegIdx+1).getImm(); |
338 | unsigned DestReg = MI.getOperand(0).getReg(); |
339 | |
340 | emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII, |
341 | *this); |
342 | MBB.erase(II); |
343 | return true; |
344 | } else { |
345 | if (AddrMode != ARMII::AddrModeT1_s) |
346 | llvm_unreachable("Unsupported addressing mode!")::llvm::llvm_unreachable_internal("Unsupported addressing mode!" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 346); |
347 | |
348 | unsigned ImmIdx = FrameRegIdx + 1; |
349 | int InstrOffs = MI.getOperand(ImmIdx).getImm(); |
350 | unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5; |
351 | unsigned Scale = 4; |
352 | |
353 | Offset += InstrOffs * Scale; |
354 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 354, __PRETTY_FUNCTION__)); |
355 | |
356 | // Common case: small offset, fits into instruction. |
357 | MachineOperand &ImmOp = MI.getOperand(ImmIdx); |
358 | int ImmedOffset = Offset / Scale; |
359 | unsigned Mask = (1 << NumBits) - 1; |
360 | |
361 | if ((unsigned)Offset <= Mask * Scale) { |
362 | // Replace the FrameIndex with the frame register (e.g., sp). |
363 | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
364 | ImmOp.ChangeToImmediate(ImmedOffset); |
365 | |
366 | // If we're using a register where sp was stored, convert the instruction |
367 | // to the non-SP version. |
368 | unsigned NewOpc = convertToNonSPOpcode(Opcode); |
369 | if (NewOpc != Opcode && FrameReg != ARM::SP) |
370 | MI.setDesc(TII.get(NewOpc)); |
371 | |
372 | return true; |
373 | } |
374 | |
375 | NumBits = 5; |
376 | Mask = (1 << NumBits) - 1; |
377 | |
378 | // If this is a thumb spill / restore, we will be using a constpool load to |
379 | // materialize the offset. |
380 | if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) { |
381 | ImmOp.ChangeToImmediate(0); |
382 | } else { |
383 | // Otherwise, it didn't fit. Pull in what we can to simplify the immed. |
384 | ImmedOffset = ImmedOffset & Mask; |
385 | ImmOp.ChangeToImmediate(ImmedOffset); |
386 | Offset &= ~(Mask * Scale); |
387 | } |
388 | } |
389 | |
390 | return Offset == 0; |
391 | } |
392 | |
393 | void Thumb1RegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, |
394 | int64_t Offset) const { |
395 | const ARMBaseInstrInfo &TII = |
396 | *static_cast<const ARMBaseInstrInfo *>(MI.getParent() |
397 | ->getParent() |
398 | ->getTarget() |
399 | .getSubtargetImpl() |
400 | ->getInstrInfo()); |
401 | int Off = Offset; // ARM doesn't need the general 64-bit offsets |
402 | unsigned i = 0; |
403 | |
404 | while (!MI.getOperand(i).isFI()) { |
405 | ++i; |
406 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 406, __PRETTY_FUNCTION__)); |
407 | } |
408 | bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII); |
409 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 409, __PRETTY_FUNCTION__)); |
410 | (void)Done; |
411 | } |
412 | |
413 | /// saveScavengerRegister - Spill the register so it can be used by the |
414 | /// register scavenger. Return true. |
415 | bool |
416 | Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB, |
417 | MachineBasicBlock::iterator I, |
418 | MachineBasicBlock::iterator &UseMI, |
419 | const TargetRegisterClass *RC, |
420 | unsigned Reg) const { |
421 | // Thumb1 can't use the emergency spill slot on the stack because |
422 | // ldr/str immediate offsets must be positive, and if we're referencing |
423 | // off the frame pointer (if, for example, there are alloca() calls in |
424 | // the function, the offset will be negative. Use R12 instead since that's |
425 | // a call clobbered register that we know won't be used in Thumb1 mode. |
426 | const TargetInstrInfo &TII = *MBB.getParent()->getSubtarget().getInstrInfo(); |
427 | DebugLoc DL; |
428 | AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr)) |
429 | .addReg(ARM::R12, RegState::Define) |
430 | .addReg(Reg, RegState::Kill)); |
431 | |
432 | // The UseMI is where we would like to restore the register. If there's |
433 | // interference with R12 before then, however, we'll need to restore it |
434 | // before that instead and adjust the UseMI. |
435 | bool done = false; |
436 | for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) { |
437 | if (II->isDebugValue()) |
438 | continue; |
439 | // If this instruction affects R12, adjust our restore point. |
440 | for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { |
441 | const MachineOperand &MO = II->getOperand(i); |
442 | if (MO.isRegMask() && MO.clobbersPhysReg(ARM::R12)) { |
443 | UseMI = II; |
444 | done = true; |
445 | break; |
446 | } |
447 | if (!MO.isReg() || MO.isUndef() || !MO.getReg() || |
448 | TargetRegisterInfo::isVirtualRegister(MO.getReg())) |
449 | continue; |
450 | if (MO.getReg() == ARM::R12) { |
451 | UseMI = II; |
452 | done = true; |
453 | break; |
454 | } |
455 | } |
456 | } |
457 | // Restore the register from R12 |
458 | AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)). |
459 | addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill)); |
460 | |
461 | return true; |
462 | } |
463 | |
464 | void |
465 | Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, |
466 | int SPAdj, unsigned FIOperandNum, |
467 | RegScavenger *RS) const { |
468 | unsigned VReg = 0; |
469 | MachineInstr &MI = *II; |
470 | MachineBasicBlock &MBB = *MI.getParent(); |
471 | MachineFunction &MF = *MBB.getParent(); |
472 | const ARMBaseInstrInfo &TII = |
473 | *static_cast<const ARMBaseInstrInfo *>(MF.getSubtarget().getInstrInfo()); |
474 | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); |
475 | DebugLoc dl = MI.getDebugLoc(); |
476 | MachineInstrBuilder MIB(*MBB.getParent(), &MI); |
477 | |
478 | unsigned FrameReg = ARM::SP; |
479 | int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); |
480 | int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + |
481 | MF.getFrameInfo()->getStackSize() + SPAdj; |
482 | |
483 | if (MF.getFrameInfo()->hasVarSizedObjects()) { |
484 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 485, __PRETTY_FUNCTION__)) |
485 | "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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 485, __PRETTY_FUNCTION__)); |
486 | // There are alloca()'s in this function, must reference off the frame |
487 | // pointer or base pointer instead. |
488 | if (!hasBasePointer(MF)) { |
489 | FrameReg = getFrameRegister(MF); |
490 | Offset -= AFI->getFramePtrSpillOffset(); |
491 | } else |
492 | FrameReg = BasePtr; |
493 | } |
494 | |
495 | // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the |
496 | // call frame setup/destroy instructions have already been eliminated. That |
497 | // means the stack pointer cannot be used to access the emergency spill slot |
498 | // when !hasReservedCallFrame(). |
499 | #ifndef NDEBUG |
500 | if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){ |
501 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 506, __PRETTY_FUNCTION__)) |
502 | .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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 506, __PRETTY_FUNCTION__)) |
503 | ->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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 506, __PRETTY_FUNCTION__)) |
504 | ->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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 506, __PRETTY_FUNCTION__)) |
505 | "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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 506, __PRETTY_FUNCTION__)) |
506 | "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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 506, __PRETTY_FUNCTION__)); |
507 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 509, __PRETTY_FUNCTION__)) |
508 | "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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 509, __PRETTY_FUNCTION__)) |
509 | "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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 509, __PRETTY_FUNCTION__)); |
510 | } |
511 | #endif // NDEBUG |
512 | |
513 | // Special handling of dbg_value instructions. |
514 | if (MI.isDebugValue()) { |
515 | MI.getOperand(FIOperandNum). ChangeToRegister(FrameReg, false /*isDef*/); |
516 | MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset); |
517 | return; |
518 | } |
519 | |
520 | // Modify MI as necessary to handle as much of 'Offset' as possible |
521 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 522, __PRETTY_FUNCTION__)) |
522 | "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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 522, __PRETTY_FUNCTION__)); |
523 | if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII)) |
524 | return; |
525 | |
526 | // If we get here, the immediate doesn't fit into the instruction. We folded |
527 | // as much as possible above, handle the rest, providing a register that is |
528 | // SP+LargeImm. |
529 | 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~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 529, __PRETTY_FUNCTION__)); |
530 | |
531 | unsigned Opcode = MI.getOpcode(); |
532 | |
533 | // Remove predicate first. |
534 | int PIdx = MI.findFirstPredOperandIdx(); |
535 | if (PIdx != -1) |
536 | removeOperands(MI, PIdx); |
537 | |
538 | if (MI.mayLoad()) { |
539 | // Use the destination register to materialize sp + offset. |
540 | unsigned TmpReg = MI.getOperand(0).getReg(); |
541 | bool UseRR = false; |
542 | if (Opcode == ARM::tLDRspi) { |
543 | if (FrameReg == ARM::SP) |
544 | emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg, |
545 | Offset, false, TII, *this); |
546 | else { |
547 | emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset); |
548 | UseRR = true; |
549 | } |
550 | } else { |
551 | emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII, |
552 | *this); |
553 | } |
554 | |
555 | MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi)); |
556 | MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true); |
557 | if (UseRR) |
558 | // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame |
559 | // register. The offset is already handled in the vreg value. |
560 | MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, |
561 | false); |
562 | } else if (MI.mayStore()) { |
563 | VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass); |
564 | bool UseRR = false; |
565 | |
566 | if (Opcode == ARM::tSTRspi) { |
567 | if (FrameReg == ARM::SP) |
568 | emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg, |
569 | Offset, false, TII, *this); |
570 | else { |
571 | emitLoadConstPool(MBB, II, dl, VReg, 0, Offset); |
572 | UseRR = true; |
573 | } |
574 | } else |
575 | emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII, |
576 | *this); |
577 | MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi)); |
578 | MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true); |
579 | if (UseRR) |
580 | // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame |
581 | // register. The offset is already handled in the vreg value. |
582 | MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false, |
583 | false); |
584 | } else { |
585 | llvm_unreachable("Unexpected opcode!")::llvm::llvm_unreachable_internal("Unexpected opcode!", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn220848/lib/Target/ARM/Thumb1RegisterInfo.cpp" , 585); |
586 | } |
587 | |
588 | // Add predicate back if it's needed. |
589 | if (MI.isPredicable()) |
590 | AddDefaultPred(MIB); |
591 | } |