/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- Thumb2InstrInfo.cpp - Thumb-2 Instruction 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-2 implementation of the TargetInstrInfo class. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "ARMMachineFunctionInfo.h" |
15 | | #include "MCTargetDesc/ARMAddressingModes.h" |
16 | | #include "Thumb2InstrInfo.h" |
17 | | #include "llvm/CodeGen/MachineBasicBlock.h" |
18 | | #include "llvm/CodeGen/MachineFrameInfo.h" |
19 | | #include "llvm/CodeGen/MachineFunction.h" |
20 | | #include "llvm/CodeGen/MachineInstr.h" |
21 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
22 | | #include "llvm/CodeGen/MachineMemOperand.h" |
23 | | #include "llvm/CodeGen/MachineOperand.h" |
24 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
25 | | #include "llvm/IR/DebugLoc.h" |
26 | | #include "llvm/MC/MCInst.h" |
27 | | #include "llvm/MC/MCInstrDesc.h" |
28 | | #include "llvm/Support/CommandLine.h" |
29 | | #include "llvm/Support/ErrorHandling.h" |
30 | | #include "llvm/Support/MathExtras.h" |
31 | | #include "llvm/Target/TargetMachine.h" |
32 | | #include "llvm/Target/TargetRegisterInfo.h" |
33 | | #include <cassert> |
34 | | |
35 | | using namespace llvm; |
36 | | |
37 | | static cl::opt<bool> |
38 | | OldT2IfCvt("old-thumb2-ifcvt", cl::Hidden, |
39 | | cl::desc("Use old-style Thumb2 if-conversion heuristics"), |
40 | | cl::init(false)); |
41 | | |
42 | | Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI) |
43 | 2.76k | : ARMBaseInstrInfo(STI) {} |
44 | | |
45 | | /// Return the noop instruction to use for a noop. |
46 | 2 | void Thumb2InstrInfo::getNoop(MCInst &NopInst) const { |
47 | 2 | NopInst.setOpcode(ARM::tHINT); |
48 | 2 | NopInst.addOperand(MCOperand::createImm(0)); |
49 | 2 | NopInst.addOperand(MCOperand::createImm(ARMCC::AL)); |
50 | 2 | NopInst.addOperand(MCOperand::createReg(0)); |
51 | 2 | } |
52 | | |
53 | 0 | unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const { |
54 | 0 | // FIXME |
55 | 0 | return 0; |
56 | 0 | } |
57 | | |
58 | | void |
59 | | Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, |
60 | 3.46k | MachineBasicBlock *NewDest) const { |
61 | 3.46k | MachineBasicBlock *MBB = Tail->getParent(); |
62 | 3.46k | ARMFunctionInfo *AFI = MBB->getParent()->getInfo<ARMFunctionInfo>(); |
63 | 3.46k | if (!AFI->hasITBlocks() || 3.46k Tail->isBranch()227 ) { |
64 | 3.23k | TargetInstrInfo::ReplaceTailWithBranchTo(Tail, NewDest); |
65 | 3.23k | return; |
66 | 3.23k | } |
67 | 227 | |
68 | 227 | // If the first instruction of Tail is predicated, we may have to update |
69 | 227 | // the IT instruction. |
70 | 227 | unsigned PredReg = 0; |
71 | 227 | ARMCC::CondCodes CC = getInstrPredicate(*Tail, PredReg); |
72 | 227 | MachineBasicBlock::iterator MBBI = Tail; |
73 | 227 | if (CC != ARMCC::AL) |
74 | 227 | // Expecting at least the t2IT instruction before it. |
75 | 0 | --MBBI; |
76 | 227 | |
77 | 227 | // Actually replace the tail. |
78 | 227 | TargetInstrInfo::ReplaceTailWithBranchTo(Tail, NewDest); |
79 | 227 | |
80 | 227 | // Fix up IT. |
81 | 227 | if (CC != ARMCC::AL227 ) { |
82 | 0 | MachineBasicBlock::iterator E = MBB->begin(); |
83 | 0 | unsigned Count = 4; // At most 4 instructions in an IT block. |
84 | 0 | while (Count && 0 MBBI != E0 ) { |
85 | 0 | if (MBBI->isDebugValue()0 ) { |
86 | 0 | --MBBI; |
87 | 0 | continue; |
88 | 0 | } |
89 | 0 | if (0 MBBI->getOpcode() == ARM::t2IT0 ) { |
90 | 0 | unsigned Mask = MBBI->getOperand(1).getImm(); |
91 | 0 | if (Count == 4) |
92 | 0 | MBBI->eraseFromParent(); |
93 | 0 | else { |
94 | 0 | unsigned MaskOn = 1 << Count; |
95 | 0 | unsigned MaskOff = ~(MaskOn - 1); |
96 | 0 | MBBI->getOperand(1).setImm((Mask & MaskOff) | MaskOn); |
97 | 0 | } |
98 | 0 | return; |
99 | 0 | } |
100 | 0 | --MBBI; |
101 | 0 | --Count; |
102 | 0 | } |
103 | 0 |
|
104 | 0 | // Ctrl flow can reach here if branch folding is run before IT block |
105 | 0 | // formation pass. |
106 | 0 | } |
107 | 3.46k | } |
108 | | |
109 | | bool |
110 | | Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB, |
111 | 788 | MachineBasicBlock::iterator MBBI) const { |
112 | 788 | while (MBBI->isDebugValue()788 ) { |
113 | 0 | ++MBBI; |
114 | 0 | if (MBBI == MBB.end()) |
115 | 0 | return false; |
116 | 0 | } |
117 | 788 | |
118 | 788 | unsigned PredReg = 0; |
119 | 788 | return getITInstrPredicate(*MBBI, PredReg) == ARMCC::AL; |
120 | 788 | } |
121 | | |
122 | | void Thumb2InstrInfo::copyPhysReg(MachineBasicBlock &MBB, |
123 | | MachineBasicBlock::iterator I, |
124 | | const DebugLoc &DL, unsigned DestReg, |
125 | 25.8k | unsigned SrcReg, bool KillSrc) const { |
126 | 25.8k | // Handle SPR, DPR, and QPR copies. |
127 | 25.8k | if (!ARM::GPRRegClass.contains(DestReg, SrcReg)) |
128 | 3.34k | return ARMBaseInstrInfo::copyPhysReg(MBB, I, DL, DestReg, SrcReg, KillSrc); |
129 | 22.4k | |
130 | 22.4k | BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) |
131 | 22.4k | .addReg(SrcReg, getKillRegState(KillSrc)) |
132 | 22.4k | .add(predOps(ARMCC::AL)); |
133 | 22.4k | } |
134 | | |
135 | | void Thumb2InstrInfo:: |
136 | | storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
137 | | unsigned SrcReg, bool isKill, int FI, |
138 | | const TargetRegisterClass *RC, |
139 | 3.41k | const TargetRegisterInfo *TRI) const { |
140 | 3.41k | DebugLoc DL; |
141 | 3.41k | if (I != MBB.end()3.41k ) DL = I->getDebugLoc()3.34k ; |
142 | 3.41k | |
143 | 3.41k | MachineFunction &MF = *MBB.getParent(); |
144 | 3.41k | MachineFrameInfo &MFI = MF.getFrameInfo(); |
145 | 3.41k | MachineMemOperand *MMO = MF.getMachineMemOperand( |
146 | 3.41k | MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, |
147 | 3.41k | MFI.getObjectSize(FI), MFI.getObjectAlignment(FI)); |
148 | 3.41k | |
149 | 3.41k | if (RC == &ARM::GPRRegClass || 3.41k RC == &ARM::tGPRRegClass1.74k || |
150 | 3.41k | RC == &ARM::tcGPRRegClass1.72k || RC == &ARM::rGPRRegClass1.72k || |
151 | 3.41k | RC == &ARM::GPRnopcRegClass936 ) { |
152 | 2.84k | BuildMI(MBB, I, DL, get(ARM::t2STRi12)) |
153 | 2.84k | .addReg(SrcReg, getKillRegState(isKill)) |
154 | 2.84k | .addFrameIndex(FI) |
155 | 2.84k | .addImm(0) |
156 | 2.84k | .addMemOperand(MMO) |
157 | 2.84k | .add(predOps(ARMCC::AL)); |
158 | 2.84k | return; |
159 | 2.84k | } |
160 | 575 | |
161 | 575 | if (575 ARM::GPRPairRegClass.hasSubClassEq(RC)575 ) { |
162 | 3 | // Thumb2 STRD expects its dest-registers to be in rGPR. Not a problem for |
163 | 3 | // gsub_0, but needs an extra constraint for gsub_1 (which could be sp |
164 | 3 | // otherwise). |
165 | 3 | if (TargetRegisterInfo::isVirtualRegister(SrcReg)3 ) { |
166 | 2 | MachineRegisterInfo *MRI = &MF.getRegInfo(); |
167 | 2 | MRI->constrainRegClass(SrcReg, &ARM::GPRPair_with_gsub_1_in_rGPRRegClass); |
168 | 2 | } |
169 | 3 | |
170 | 3 | MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2STRDi8)); |
171 | 3 | AddDReg(MIB, SrcReg, ARM::gsub_0, getKillRegState(isKill), TRI); |
172 | 3 | AddDReg(MIB, SrcReg, ARM::gsub_1, 0, TRI); |
173 | 3 | MIB.addFrameIndex(FI).addImm(0).addMemOperand(MMO).add(predOps(ARMCC::AL)); |
174 | 3 | return; |
175 | 3 | } |
176 | 572 | |
177 | 572 | ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC, TRI); |
178 | 572 | } |
179 | | |
180 | | void Thumb2InstrInfo:: |
181 | | loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
182 | | unsigned DestReg, int FI, |
183 | | const TargetRegisterClass *RC, |
184 | 4.15k | const TargetRegisterInfo *TRI) const { |
185 | 4.15k | MachineFunction &MF = *MBB.getParent(); |
186 | 4.15k | MachineFrameInfo &MFI = MF.getFrameInfo(); |
187 | 4.15k | MachineMemOperand *MMO = MF.getMachineMemOperand( |
188 | 4.15k | MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, |
189 | 4.15k | MFI.getObjectSize(FI), MFI.getObjectAlignment(FI)); |
190 | 4.15k | DebugLoc DL; |
191 | 4.15k | if (I != MBB.end()4.15k ) DL = I->getDebugLoc()4.15k ; |
192 | 4.15k | |
193 | 4.15k | if (RC == &ARM::GPRRegClass || 4.15k RC == &ARM::tGPRRegClass2.17k || |
194 | 4.15k | RC == &ARM::tcGPRRegClass2.17k || RC == &ARM::rGPRRegClass2.17k || |
195 | 4.15k | RC == &ARM::GPRnopcRegClass1.24k ) { |
196 | 3.46k | BuildMI(MBB, I, DL, get(ARM::t2LDRi12), DestReg) |
197 | 3.46k | .addFrameIndex(FI) |
198 | 3.46k | .addImm(0) |
199 | 3.46k | .addMemOperand(MMO) |
200 | 3.46k | .add(predOps(ARMCC::AL)); |
201 | 3.46k | return; |
202 | 3.46k | } |
203 | 685 | |
204 | 685 | if (685 ARM::GPRPairRegClass.hasSubClassEq(RC)685 ) { |
205 | 2 | // Thumb2 LDRD expects its dest-registers to be in rGPR. Not a problem for |
206 | 2 | // gsub_0, but needs an extra constraint for gsub_1 (which could be sp |
207 | 2 | // otherwise). |
208 | 2 | if (TargetRegisterInfo::isVirtualRegister(DestReg)2 ) { |
209 | 2 | MachineRegisterInfo *MRI = &MF.getRegInfo(); |
210 | 2 | MRI->constrainRegClass(DestReg, |
211 | 2 | &ARM::GPRPair_with_gsub_1_in_rGPRRegClass); |
212 | 2 | } |
213 | 2 | |
214 | 2 | MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2LDRDi8)); |
215 | 2 | AddDReg(MIB, DestReg, ARM::gsub_0, RegState::DefineNoRead, TRI); |
216 | 2 | AddDReg(MIB, DestReg, ARM::gsub_1, RegState::DefineNoRead, TRI); |
217 | 2 | MIB.addFrameIndex(FI).addImm(0).addMemOperand(MMO).add(predOps(ARMCC::AL)); |
218 | 2 | |
219 | 2 | if (TargetRegisterInfo::isPhysicalRegister(DestReg)) |
220 | 0 | MIB.addReg(DestReg, RegState::ImplicitDefine); |
221 | 2 | return; |
222 | 2 | } |
223 | 683 | |
224 | 683 | ARMBaseInstrInfo::loadRegFromStackSlot(MBB, I, DestReg, FI, RC, TRI); |
225 | 683 | } |
226 | | |
227 | | void Thumb2InstrInfo::expandLoadStackGuard( |
228 | 130 | MachineBasicBlock::iterator MI) const { |
229 | 130 | MachineFunction &MF = *MI->getParent()->getParent(); |
230 | 130 | if (MF.getTarget().isPositionIndependent()) |
231 | 126 | expandLoadStackGuardBase(MI, ARM::t2MOV_ga_pcrel, ARM::t2LDRi12); |
232 | 130 | else |
233 | 4 | expandLoadStackGuardBase(MI, ARM::t2MOVi32imm, ARM::t2LDRi12); |
234 | 130 | } |
235 | | |
236 | | void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, |
237 | | MachineBasicBlock::iterator &MBBI, |
238 | | const DebugLoc &dl, unsigned DestReg, |
239 | | unsigned BaseReg, int NumBytes, |
240 | | ARMCC::CondCodes Pred, unsigned PredReg, |
241 | | const ARMBaseInstrInfo &TII, |
242 | 8.01k | unsigned MIFlags) { |
243 | 8.01k | if (NumBytes == 0 && 8.01k DestReg != BaseReg658 ) { |
244 | 658 | BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) |
245 | 658 | .addReg(BaseReg, RegState::Kill) |
246 | 658 | .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags); |
247 | 658 | return; |
248 | 658 | } |
249 | 7.36k | |
250 | 7.36k | bool isSub = NumBytes < 0; |
251 | 7.36k | if (isSub7.36k ) NumBytes = -NumBytes2.09k ; |
252 | 7.36k | |
253 | 7.36k | // If profitable, use a movw or movt to materialize the offset. |
254 | 7.36k | // FIXME: Use the scavenger to grab a scratch register. |
255 | 7.36k | if (DestReg != ARM::SP && 7.36k DestReg != BaseReg3.52k && |
256 | 3.52k | NumBytes >= 4096 && |
257 | 7.36k | ARM_AM::getT2SOImmVal(NumBytes) == -1315 ) { |
258 | 66 | bool Fits = false; |
259 | 66 | if (NumBytes < 6553666 ) { |
260 | 66 | // Use a movw to materialize the 16-bit constant. |
261 | 66 | BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg) |
262 | 66 | .addImm(NumBytes) |
263 | 66 | .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags); |
264 | 66 | Fits = true; |
265 | 66 | } else if (0 (NumBytes & 0xffff) == 00 ) { |
266 | 0 | // Use a movt to materialize the 32-bit constant. |
267 | 0 | BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg) |
268 | 0 | .addReg(DestReg) |
269 | 0 | .addImm(NumBytes >> 16) |
270 | 0 | .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags); |
271 | 0 | Fits = true; |
272 | 0 | } |
273 | 66 | |
274 | 66 | if (Fits66 ) { |
275 | 66 | if (isSub66 ) { |
276 | 0 | BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg) |
277 | 0 | .addReg(BaseReg) |
278 | 0 | .addReg(DestReg, RegState::Kill) |
279 | 0 | .add(predOps(Pred, PredReg)) |
280 | 0 | .add(condCodeOp()) |
281 | 0 | .setMIFlags(MIFlags); |
282 | 66 | } else { |
283 | 66 | // Here we know that DestReg is not SP but we do not |
284 | 66 | // know anything about BaseReg. t2ADDrr is an invalid |
285 | 66 | // instruction is SP is used as the second argument, but |
286 | 66 | // is fine if SP is the first argument. To be sure we |
287 | 66 | // do not generate invalid encoding, put BaseReg first. |
288 | 66 | BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg) |
289 | 66 | .addReg(BaseReg) |
290 | 66 | .addReg(DestReg, RegState::Kill) |
291 | 66 | .add(predOps(Pred, PredReg)) |
292 | 66 | .add(condCodeOp()) |
293 | 66 | .setMIFlags(MIFlags); |
294 | 66 | } |
295 | 66 | return; |
296 | 66 | } |
297 | 7.29k | } |
298 | 7.29k | |
299 | 14.6k | while (7.29k NumBytes14.6k ) { |
300 | 7.32k | unsigned ThisVal = NumBytes; |
301 | 7.32k | unsigned Opc = 0; |
302 | 7.32k | if (DestReg == ARM::SP && 7.32k BaseReg != ARM::SP3.86k ) { |
303 | 0 | // mov sp, rn. Note t2MOVr cannot be used. |
304 | 0 | BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg) |
305 | 0 | .addReg(BaseReg) |
306 | 0 | .setMIFlags(MIFlags) |
307 | 0 | .add(predOps(ARMCC::AL)); |
308 | 0 | BaseReg = ARM::SP; |
309 | 0 | continue; |
310 | 0 | } |
311 | 7.32k | |
312 | 7.32k | bool HasCCOut = true; |
313 | 7.32k | if (BaseReg == ARM::SP7.32k ) { |
314 | 6.86k | // sub sp, sp, #imm7 |
315 | 6.86k | if (DestReg == ARM::SP && 6.86k (ThisVal < ((1 << 7)-1) * 4)3.86k ) { |
316 | 3.73k | assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?"); |
317 | 3.73k | Opc = isSub ? ARM::tSUBspi1.88k : ARM::tADDspi1.85k ; |
318 | 3.73k | BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) |
319 | 3.73k | .addReg(BaseReg) |
320 | 3.73k | .addImm(ThisVal / 4) |
321 | 3.73k | .setMIFlags(MIFlags) |
322 | 3.73k | .add(predOps(ARMCC::AL)); |
323 | 3.73k | NumBytes = 0; |
324 | 3.73k | continue; |
325 | 3.73k | } |
326 | 3.13k | |
327 | 3.13k | // sub rd, sp, so_imm |
328 | 3.13k | Opc = isSub ? 3.13k ARM::t2SUBri70 : ARM::t2ADDri3.06k ; |
329 | 3.13k | if (ARM_AM::getT2SOImmVal(NumBytes) != -13.13k ) { |
330 | 3.09k | NumBytes = 0; |
331 | 3.13k | } else { |
332 | 32 | // FIXME: Move this to ARMAddressingModes.h? |
333 | 32 | unsigned RotAmt = countLeadingZeros(ThisVal); |
334 | 32 | ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); |
335 | 32 | NumBytes &= ~ThisVal; |
336 | 32 | assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && |
337 | 32 | "Bit extraction didn't work?"); |
338 | 32 | } |
339 | 7.32k | } else { |
340 | 460 | assert(DestReg != ARM::SP && BaseReg != ARM::SP); |
341 | 460 | Opc = isSub ? ARM::t2SUBri158 : ARM::t2ADDri302 ; |
342 | 460 | if (ARM_AM::getT2SOImmVal(NumBytes) != -1460 ) { |
343 | 460 | NumBytes = 0; |
344 | 460 | } else if (0 ThisVal < 40960 ) { |
345 | 0 | Opc = isSub ? ARM::t2SUBri120 : ARM::t2ADDri120 ; |
346 | 0 | HasCCOut = false; |
347 | 0 | NumBytes = 0; |
348 | 0 | } else { |
349 | 0 | // FIXME: Move this to ARMAddressingModes.h? |
350 | 0 | unsigned RotAmt = countLeadingZeros(ThisVal); |
351 | 0 | ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); |
352 | 0 | NumBytes &= ~ThisVal; |
353 | 0 | assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && |
354 | 0 | "Bit extraction didn't work?"); |
355 | 0 | } |
356 | 460 | } |
357 | 7.32k | |
358 | 7.32k | // Build the new ADD / SUB. |
359 | 3.59k | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) |
360 | 3.59k | .addReg(BaseReg, RegState::Kill) |
361 | 3.59k | .addImm(ThisVal) |
362 | 3.59k | .add(predOps(ARMCC::AL)) |
363 | 3.59k | .setMIFlags(MIFlags); |
364 | 3.59k | if (HasCCOut) |
365 | 3.59k | MIB.add(condCodeOp()); |
366 | 7.32k | |
367 | 7.32k | BaseReg = DestReg; |
368 | 7.32k | } |
369 | 8.01k | } |
370 | | |
371 | | static unsigned |
372 | | negativeOffsetOpcode(unsigned opcode) |
373 | 219 | { |
374 | 219 | switch (opcode) { |
375 | 98 | case ARM::t2LDRi12: return ARM::t2LDRi8; |
376 | 0 | case ARM::t2LDRHi12: return ARM::t2LDRHi8; |
377 | 0 | case ARM::t2LDRBi12: return ARM::t2LDRBi8; |
378 | 0 | case ARM::t2LDRSHi12: return ARM::t2LDRSHi8; |
379 | 0 | case ARM::t2LDRSBi12: return ARM::t2LDRSBi8; |
380 | 121 | case ARM::t2STRi12: return ARM::t2STRi8; |
381 | 0 | case ARM::t2STRBi12: return ARM::t2STRBi8; |
382 | 0 | case ARM::t2STRHi12: return ARM::t2STRHi8; |
383 | 0 | case ARM::t2PLDi12: return ARM::t2PLDi8; |
384 | 219 | |
385 | 0 | case ARM::t2LDRi8: |
386 | 0 | case ARM::t2LDRHi8: |
387 | 0 | case ARM::t2LDRBi8: |
388 | 0 | case ARM::t2LDRSHi8: |
389 | 0 | case ARM::t2LDRSBi8: |
390 | 0 | case ARM::t2STRi8: |
391 | 0 | case ARM::t2STRBi8: |
392 | 0 | case ARM::t2STRHi8: |
393 | 0 | case ARM::t2PLDi8: |
394 | 0 | return opcode; |
395 | 0 |
|
396 | 0 | default: |
397 | 0 | break; |
398 | 0 | } |
399 | 0 |
|
400 | 0 | return 0; |
401 | 0 | } |
402 | | |
403 | | static unsigned |
404 | | positiveOffsetOpcode(unsigned opcode) |
405 | 11.4k | { |
406 | 11.4k | switch (opcode) { |
407 | 0 | case ARM::t2LDRi8: return ARM::t2LDRi12; |
408 | 0 | case ARM::t2LDRHi8: return ARM::t2LDRHi12; |
409 | 0 | case ARM::t2LDRBi8: return ARM::t2LDRBi12; |
410 | 0 | case ARM::t2LDRSHi8: return ARM::t2LDRSHi12; |
411 | 0 | case ARM::t2LDRSBi8: return ARM::t2LDRSBi12; |
412 | 0 | case ARM::t2STRi8: return ARM::t2STRi12; |
413 | 0 | case ARM::t2STRBi8: return ARM::t2STRBi12; |
414 | 0 | case ARM::t2STRHi8: return ARM::t2STRHi12; |
415 | 0 | case ARM::t2PLDi8: return ARM::t2PLDi12; |
416 | 11.4k | |
417 | 11.4k | case ARM::t2LDRi12: |
418 | 11.4k | case ARM::t2LDRHi12: |
419 | 11.4k | case ARM::t2LDRBi12: |
420 | 11.4k | case ARM::t2LDRSHi12: |
421 | 11.4k | case ARM::t2LDRSBi12: |
422 | 11.4k | case ARM::t2STRi12: |
423 | 11.4k | case ARM::t2STRBi12: |
424 | 11.4k | case ARM::t2STRHi12: |
425 | 11.4k | case ARM::t2PLDi12: |
426 | 11.4k | return opcode; |
427 | 11.4k | |
428 | 0 | default: |
429 | 0 | break; |
430 | 0 | } |
431 | 0 |
|
432 | 0 | return 0; |
433 | 0 | } |
434 | | |
435 | | static unsigned |
436 | | immediateOffsetOpcode(unsigned opcode) |
437 | 0 | { |
438 | 0 | switch (opcode) { |
439 | 0 | case ARM::t2LDRs: return ARM::t2LDRi12; |
440 | 0 | case ARM::t2LDRHs: return ARM::t2LDRHi12; |
441 | 0 | case ARM::t2LDRBs: return ARM::t2LDRBi12; |
442 | 0 | case ARM::t2LDRSHs: return ARM::t2LDRSHi12; |
443 | 0 | case ARM::t2LDRSBs: return ARM::t2LDRSBi12; |
444 | 0 | case ARM::t2STRs: return ARM::t2STRi12; |
445 | 0 | case ARM::t2STRBs: return ARM::t2STRBi12; |
446 | 0 | case ARM::t2STRHs: return ARM::t2STRHi12; |
447 | 0 | case ARM::t2PLDs: return ARM::t2PLDi12; |
448 | 0 |
|
449 | 0 | case ARM::t2LDRi12: |
450 | 0 | case ARM::t2LDRHi12: |
451 | 0 | case ARM::t2LDRBi12: |
452 | 0 | case ARM::t2LDRSHi12: |
453 | 0 | case ARM::t2LDRSBi12: |
454 | 0 | case ARM::t2STRi12: |
455 | 0 | case ARM::t2STRBi12: |
456 | 0 | case ARM::t2STRHi12: |
457 | 0 | case ARM::t2PLDi12: |
458 | 0 | case ARM::t2LDRi8: |
459 | 0 | case ARM::t2LDRHi8: |
460 | 0 | case ARM::t2LDRBi8: |
461 | 0 | case ARM::t2LDRSHi8: |
462 | 0 | case ARM::t2LDRSBi8: |
463 | 0 | case ARM::t2STRi8: |
464 | 0 | case ARM::t2STRBi8: |
465 | 0 | case ARM::t2STRHi8: |
466 | 0 | case ARM::t2PLDi8: |
467 | 0 | return opcode; |
468 | 0 |
|
469 | 0 | default: |
470 | 0 | break; |
471 | 0 | } |
472 | 0 |
|
473 | 0 | return 0; |
474 | 0 | } |
475 | | |
476 | | bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, |
477 | | unsigned FrameReg, int &Offset, |
478 | 15.1k | const ARMBaseInstrInfo &TII) { |
479 | 15.1k | unsigned Opcode = MI.getOpcode(); |
480 | 15.1k | const MCInstrDesc &Desc = MI.getDesc(); |
481 | 15.1k | unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); |
482 | 15.1k | bool isSub = false; |
483 | 15.1k | |
484 | 15.1k | // Memory operands in inline assembly always use AddrModeT2_i12. |
485 | 15.1k | if (Opcode == ARM::INLINEASM) |
486 | 0 | AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2? |
487 | 15.1k | |
488 | 15.1k | if (Opcode == ARM::t2ADDri || 15.1k Opcode == ARM::t2ADDri1213.0k ) { |
489 | 2.02k | Offset += MI.getOperand(FrameRegIdx+1).getImm(); |
490 | 2.02k | |
491 | 2.02k | unsigned PredReg; |
492 | 2.02k | if (Offset == 0 && 2.02k getInstrPredicate(MI, PredReg) == ARMCC::AL228 ) { |
493 | 228 | // Turn it into a move. |
494 | 228 | MI.setDesc(TII.get(ARM::tMOVr)); |
495 | 228 | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
496 | 228 | // Remove offset and remaining explicit predicate operands. |
497 | 912 | do MI.RemoveOperand(FrameRegIdx+1); |
498 | 912 | while (MI.getNumOperands() > FrameRegIdx+1); |
499 | 228 | MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI); |
500 | 228 | MIB.add(predOps(ARMCC::AL)); |
501 | 228 | return true; |
502 | 228 | } |
503 | 1.79k | |
504 | 1.79k | bool HasCCOut = Opcode != ARM::t2ADDri12; |
505 | 1.79k | |
506 | 1.79k | if (Offset < 01.79k ) { |
507 | 45 | Offset = -Offset; |
508 | 45 | isSub = true; |
509 | 45 | MI.setDesc(TII.get(ARM::t2SUBri)); |
510 | 1.79k | } else { |
511 | 1.75k | MI.setDesc(TII.get(ARM::t2ADDri)); |
512 | 1.75k | } |
513 | 1.79k | |
514 | 1.79k | // Common case: small offset, fits into instruction. |
515 | 1.79k | if (ARM_AM::getT2SOImmVal(Offset) != -11.79k ) { |
516 | 1.50k | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
517 | 1.50k | MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); |
518 | 1.50k | // Add cc_out operand if the original instruction did not have one. |
519 | 1.50k | if (!HasCCOut) |
520 | 0 | MI.addOperand(MachineOperand::CreateReg(0, false)); |
521 | 1.50k | Offset = 0; |
522 | 1.50k | return true; |
523 | 1.50k | } |
524 | 291 | // Another common case: imm12. |
525 | 291 | if (291 Offset < 4096 && |
526 | 291 | (!HasCCOut || 279 MI.getOperand(MI.getNumOperands()-1).getReg() == 0279 )) { |
527 | 279 | unsigned NewOpc = isSub ? ARM::t2SUBri120 : ARM::t2ADDri12279 ; |
528 | 279 | MI.setDesc(TII.get(NewOpc)); |
529 | 279 | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
530 | 279 | MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); |
531 | 279 | // Remove the cc_out operand. |
532 | 279 | if (HasCCOut) |
533 | 279 | MI.RemoveOperand(MI.getNumOperands()-1); |
534 | 279 | Offset = 0; |
535 | 279 | return true; |
536 | 279 | } |
537 | 12 | |
538 | 12 | // Otherwise, extract 8 adjacent bits from the immediate into this |
539 | 12 | // t2ADDri/t2SUBri. |
540 | 12 | unsigned RotAmt = countLeadingZeros<unsigned>(Offset); |
541 | 12 | unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt); |
542 | 12 | |
543 | 12 | // We will handle these bits from offset, clear them. |
544 | 12 | Offset &= ~ThisImmVal; |
545 | 12 | |
546 | 12 | assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 && |
547 | 12 | "Bit extraction didn't work?"); |
548 | 12 | MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal); |
549 | 12 | // Add cc_out operand if the original instruction did not have one. |
550 | 12 | if (!HasCCOut) |
551 | 0 | MI.addOperand(MachineOperand::CreateReg(0, false)); |
552 | 15.1k | } else { |
553 | 13.0k | // AddrMode4 and AddrMode6 cannot handle any offset. |
554 | 13.0k | if (AddrMode == ARMII::AddrMode4 || 13.0k AddrMode == ARMII::AddrMode613.0k ) |
555 | 596 | return false; |
556 | 12.5k | |
557 | 12.5k | // AddrModeT2_so cannot handle any offset. If there is no offset |
558 | 12.5k | // register then we change to an immediate version. |
559 | 12.5k | unsigned NewOpc = Opcode; |
560 | 12.5k | if (AddrMode == ARMII::AddrModeT2_so12.5k ) { |
561 | 0 | unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg(); |
562 | 0 | if (OffsetReg != 00 ) { |
563 | 0 | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
564 | 0 | return Offset == 0; |
565 | 0 | } |
566 | 0 |
|
567 | 0 | MI.RemoveOperand(FrameRegIdx+1); |
568 | 0 | MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0); |
569 | 0 | NewOpc = immediateOffsetOpcode(Opcode); |
570 | 0 | AddrMode = ARMII::AddrModeT2_i12; |
571 | 0 | } |
572 | 12.5k | |
573 | 12.5k | unsigned NumBits = 0; |
574 | 12.5k | unsigned Scale = 1; |
575 | 12.5k | if (AddrMode == ARMII::AddrModeT2_i8 || 12.5k AddrMode == ARMII::AddrModeT2_i1212.5k ) { |
576 | 11.6k | // i8 supports only negative, and i12 supports only positive, so |
577 | 11.6k | // based on Offset sign convert Opcode to the appropriate |
578 | 11.6k | // instruction |
579 | 11.6k | Offset += MI.getOperand(FrameRegIdx+1).getImm(); |
580 | 11.6k | if (Offset < 011.6k ) { |
581 | 219 | NewOpc = negativeOffsetOpcode(Opcode); |
582 | 219 | NumBits = 8; |
583 | 219 | isSub = true; |
584 | 219 | Offset = -Offset; |
585 | 11.6k | } else { |
586 | 11.4k | NewOpc = positiveOffsetOpcode(Opcode); |
587 | 11.4k | NumBits = 12; |
588 | 11.4k | } |
589 | 12.5k | } else if (813 AddrMode == ARMII::AddrMode5813 ) { |
590 | 808 | // VFP address mode. |
591 | 808 | const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1); |
592 | 808 | int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm()); |
593 | 808 | if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub) |
594 | 0 | InstrOffs *= -1; |
595 | 808 | NumBits = 8; |
596 | 808 | Scale = 4; |
597 | 808 | Offset += InstrOffs * 4; |
598 | 808 | assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); |
599 | 808 | if (Offset < 0808 ) { |
600 | 0 | Offset = -Offset; |
601 | 0 | isSub = true; |
602 | 0 | } |
603 | 813 | } else if (5 AddrMode == ARMII::AddrModeT2_i8s45 ) { |
604 | 5 | Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4; |
605 | 5 | NumBits = 10; // 8 bits scaled by 4 |
606 | 5 | // MCInst operand expects already scaled value. |
607 | 5 | Scale = 1; |
608 | 5 | assert((Offset & 3) == 0 && "Can't encode this offset!"); |
609 | 5 | } else { |
610 | 0 | llvm_unreachable("Unsupported addressing mode!"); |
611 | 813 | } |
612 | 12.5k | |
613 | 12.5k | if (12.5k NewOpc != Opcode12.5k ) |
614 | 219 | MI.setDesc(TII.get(NewOpc)); |
615 | 12.5k | |
616 | 12.5k | MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1); |
617 | 12.5k | |
618 | 12.5k | // Attempt to fold address computation |
619 | 12.5k | // Common case: small offset, fits into instruction. |
620 | 12.5k | int ImmedOffset = Offset / Scale; |
621 | 12.5k | unsigned Mask = (1 << NumBits) - 1; |
622 | 12.5k | if ((unsigned)Offset <= Mask * Scale12.5k ) { |
623 | 12.0k | // Replace the FrameIndex with fp/sp |
624 | 12.0k | MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); |
625 | 12.0k | if (isSub12.0k ) { |
626 | 219 | if (AddrMode == ARMII::AddrMode5) |
627 | 219 | // FIXME: Not consistent. |
628 | 0 | ImmedOffset |= 1 << NumBits; |
629 | 219 | else |
630 | 219 | ImmedOffset = -ImmedOffset; |
631 | 219 | } |
632 | 12.0k | ImmOp.ChangeToImmediate(ImmedOffset); |
633 | 12.0k | Offset = 0; |
634 | 12.0k | return true; |
635 | 12.0k | } |
636 | 453 | |
637 | 453 | // Otherwise, offset doesn't fit. Pull in what we can to simplify |
638 | 453 | ImmedOffset = ImmedOffset & Mask; |
639 | 453 | if (isSub453 ) { |
640 | 0 | if (AddrMode == ARMII::AddrMode5) |
641 | 0 | // FIXME: Not consistent. |
642 | 0 | ImmedOffset |= 1 << NumBits; |
643 | 0 | else { |
644 | 0 | ImmedOffset = -ImmedOffset; |
645 | 0 | if (ImmedOffset == 0) |
646 | 0 | // Change the opcode back if the encoded offset is zero. |
647 | 0 | MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc))); |
648 | 0 | } |
649 | 0 | } |
650 | 13.0k | ImmOp.ChangeToImmediate(ImmedOffset); |
651 | 13.0k | Offset &= ~(Mask*Scale); |
652 | 13.0k | } |
653 | 15.1k | |
654 | 465 | Offset = (isSub) ? 465 -Offset0 : Offset465 ; |
655 | 465 | return Offset == 0; |
656 | 15.1k | } |
657 | | |
658 | | ARMCC::CondCodes llvm::getITInstrPredicate(const MachineInstr &MI, |
659 | 302k | unsigned &PredReg) { |
660 | 302k | unsigned Opc = MI.getOpcode(); |
661 | 302k | if (Opc == ARM::tBcc || 302k Opc == ARM::t2Bcc302k ) |
662 | 18.6k | return ARMCC::AL; |
663 | 284k | return getInstrPredicate(MI, PredReg); |
664 | 284k | } |