Line data Source code
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 "Thumb2InstrInfo.h"
15 : #include "ARMMachineFunctionInfo.h"
16 : #include "MCTargetDesc/ARMAddressingModes.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/CodeGen/TargetRegisterInfo.h"
26 : #include "llvm/IR/DebugLoc.h"
27 : #include "llvm/MC/MCInst.h"
28 : #include "llvm/MC/MCInstrDesc.h"
29 : #include "llvm/Support/CommandLine.h"
30 : #include "llvm/Support/ErrorHandling.h"
31 : #include "llvm/Support/MathExtras.h"
32 : #include "llvm/Target/TargetMachine.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 1557 : Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget &STI)
43 1557 : : ARMBaseInstrInfo(STI) {}
44 :
45 : /// Return the noop instruction to use for a noop.
46 0 : void Thumb2InstrInfo::getNoop(MCInst &NopInst) const {
47 : NopInst.setOpcode(ARM::tHINT);
48 0 : NopInst.addOperand(MCOperand::createImm(0));
49 0 : NopInst.addOperand(MCOperand::createImm(ARMCC::AL));
50 0 : NopInst.addOperand(MCOperand::createReg(0));
51 0 : }
52 :
53 0 : unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const {
54 : // FIXME
55 0 : return 0;
56 : }
57 :
58 : void
59 95 : Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail,
60 : MachineBasicBlock *NewDest) const {
61 95 : MachineBasicBlock *MBB = Tail->getParent();
62 95 : ARMFunctionInfo *AFI = MBB->getParent()->getInfo<ARMFunctionInfo>();
63 96 : if (!AFI->hasITBlocks() || Tail->isBranch()) {
64 94 : TargetInstrInfo::ReplaceTailWithBranchTo(Tail, NewDest);
65 94 : return;
66 : }
67 :
68 : // If the first instruction of Tail is predicated, we may have to update
69 : // the IT instruction.
70 1 : unsigned PredReg = 0;
71 1 : ARMCC::CondCodes CC = getInstrPredicate(*Tail, PredReg);
72 1 : MachineBasicBlock::iterator MBBI = Tail;
73 1 : if (CC != ARMCC::AL)
74 : // Expecting at least the t2IT instruction before it.
75 : --MBBI;
76 :
77 : // Actually replace the tail.
78 1 : TargetInstrInfo::ReplaceTailWithBranchTo(Tail, NewDest);
79 :
80 : // Fix up IT.
81 1 : if (CC != ARMCC::AL) {
82 : MachineBasicBlock::iterator E = MBB->begin();
83 : unsigned Count = 4; // At most 4 instructions in an IT block.
84 0 : while (Count && MBBI != E) {
85 : if (MBBI->isDebugInstr()) {
86 : --MBBI;
87 0 : continue;
88 : }
89 0 : if (MBBI->getOpcode() == ARM::t2IT) {
90 0 : unsigned Mask = MBBI->getOperand(1).getImm();
91 0 : if (Count == 4)
92 0 : MBBI->eraseFromParent();
93 : else {
94 0 : unsigned MaskOn = 1 << Count;
95 0 : unsigned MaskOff = ~(MaskOn - 1);
96 0 : MBBI->getOperand(1).setImm((Mask & MaskOff) | MaskOn);
97 : }
98 : return;
99 : }
100 : --MBBI;
101 0 : --Count;
102 : }
103 :
104 : // Ctrl flow can reach here if branch folding is run before IT block
105 : // formation pass.
106 : }
107 : }
108 :
109 : bool
110 29 : Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,
111 : MachineBasicBlock::iterator MBBI) const {
112 : while (MBBI->isDebugInstr()) {
113 : ++MBBI;
114 0 : if (MBBI == MBB.end())
115 : return false;
116 : }
117 :
118 29 : unsigned PredReg = 0;
119 29 : return getITInstrPredicate(*MBBI, PredReg) == ARMCC::AL;
120 : }
121 :
122 4858 : void Thumb2InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
123 : MachineBasicBlock::iterator I,
124 : const DebugLoc &DL, unsigned DestReg,
125 : unsigned SrcReg, bool KillSrc) const {
126 : // Handle SPR, DPR, and QPR copies.
127 9716 : if (!ARM::GPRRegClass.contains(DestReg, SrcReg))
128 2437 : return ARMBaseInstrInfo::copyPhysReg(MBB, I, DL, DestReg, SrcReg, KillSrc);
129 :
130 4842 : BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg)
131 2421 : .addReg(SrcReg, getKillRegState(KillSrc))
132 2421 : .add(predOps(ARMCC::AL));
133 : }
134 :
135 1132 : void Thumb2InstrInfo::
136 : storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
137 : unsigned SrcReg, bool isKill, int FI,
138 : const TargetRegisterClass *RC,
139 : const TargetRegisterInfo *TRI) const {
140 1132 : DebugLoc DL;
141 1132 : if (I != MBB.end()) DL = I->getDebugLoc();
142 :
143 1132 : MachineFunction &MF = *MBB.getParent();
144 1132 : MachineFrameInfo &MFI = MF.getFrameInfo();
145 1132 : MachineMemOperand *MMO = MF.getMachineMemOperand(
146 : MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
147 : MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));
148 :
149 1132 : if (RC == &ARM::GPRRegClass || RC == &ARM::tGPRRegClass ||
150 823 : RC == &ARM::tcGPRRegClass || RC == &ARM::rGPRRegClass ||
151 : RC == &ARM::GPRnopcRegClass) {
152 1002 : BuildMI(MBB, I, DL, get(ARM::t2STRi12))
153 501 : .addReg(SrcReg, getKillRegState(isKill))
154 : .addFrameIndex(FI)
155 : .addImm(0)
156 : .addMemOperand(MMO)
157 501 : .add(predOps(ARMCC::AL));
158 501 : return;
159 : }
160 :
161 1262 : if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
162 : // Thumb2 STRD expects its dest-registers to be in rGPR. Not a problem for
163 : // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
164 : // otherwise).
165 3 : if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
166 2 : MachineRegisterInfo *MRI = &MF.getRegInfo();
167 2 : MRI->constrainRegClass(SrcReg, &ARM::GPRPair_with_gsub_1_in_rGPRRegClass);
168 : }
169 :
170 6 : 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 : return;
175 : }
176 :
177 628 : ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC, TRI);
178 : }
179 :
180 1306 : void Thumb2InstrInfo::
181 : loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
182 : unsigned DestReg, int FI,
183 : const TargetRegisterClass *RC,
184 : const TargetRegisterInfo *TRI) const {
185 1306 : MachineFunction &MF = *MBB.getParent();
186 1306 : MachineFrameInfo &MFI = MF.getFrameInfo();
187 1306 : MachineMemOperand *MMO = MF.getMachineMemOperand(
188 : MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
189 : MFI.getObjectSize(FI), MFI.getObjectAlignment(FI));
190 1306 : DebugLoc DL;
191 1306 : if (I != MBB.end()) DL = I->getDebugLoc();
192 :
193 1306 : if (RC == &ARM::GPRRegClass || RC == &ARM::tGPRRegClass ||
194 1152 : RC == &ARM::tcGPRRegClass || RC == &ARM::rGPRRegClass ||
195 : RC == &ARM::GPRnopcRegClass) {
196 1176 : BuildMI(MBB, I, DL, get(ARM::t2LDRi12), DestReg)
197 : .addFrameIndex(FI)
198 : .addImm(0)
199 : .addMemOperand(MMO)
200 588 : .add(predOps(ARMCC::AL));
201 588 : return;
202 : }
203 :
204 1436 : if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
205 : // Thumb2 LDRD expects its dest-registers to be in rGPR. Not a problem for
206 : // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
207 : // otherwise).
208 2 : if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
209 2 : MachineRegisterInfo *MRI = &MF.getRegInfo();
210 2 : MRI->constrainRegClass(DestReg,
211 : &ARM::GPRPair_with_gsub_1_in_rGPRRegClass);
212 : }
213 :
214 4 : 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 :
219 2 : if (TargetRegisterInfo::isPhysicalRegister(DestReg))
220 0 : MIB.addReg(DestReg, RegState::ImplicitDefine);
221 : return;
222 : }
223 :
224 716 : ARMBaseInstrInfo::loadRegFromStackSlot(MBB, I, DestReg, FI, RC, TRI);
225 : }
226 :
227 34 : void Thumb2InstrInfo::expandLoadStackGuard(
228 : MachineBasicBlock::iterator MI) const {
229 34 : MachineFunction &MF = *MI->getParent()->getParent();
230 34 : if (MF.getTarget().isPositionIndependent())
231 30 : expandLoadStackGuardBase(MI, ARM::t2MOV_ga_pcrel, ARM::t2LDRi12);
232 : else
233 4 : expandLoadStackGuardBase(MI, ARM::t2MOVi32imm, ARM::t2LDRi12);
234 34 : }
235 :
236 2599 : 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 : unsigned MIFlags) {
243 2599 : if (NumBytes == 0 && DestReg != BaseReg) {
244 372 : BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
245 186 : .addReg(BaseReg, RegState::Kill)
246 186 : .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
247 186 : return;
248 : }
249 :
250 : bool isSub = NumBytes < 0;
251 2413 : if (isSub) NumBytes = -NumBytes;
252 :
253 : // If profitable, use a movw or movt to materialize the offset.
254 : // FIXME: Use the scavenger to grab a scratch register.
255 1445 : if (DestReg != ARM::SP && DestReg != BaseReg &&
256 2413 : NumBytes >= 4096 &&
257 437 : ARM_AM::getT2SOImmVal(NumBytes) == -1) {
258 : bool Fits = false;
259 133 : if (NumBytes < 65536) {
260 : // Use a movw to materialize the 16-bit constant.
261 399 : BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg)
262 133 : .addImm(NumBytes)
263 133 : .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
264 : Fits = true;
265 0 : } else if ((NumBytes & 0xffff) == 0) {
266 : // 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 : Fits = true;
272 : }
273 :
274 : if (Fits) {
275 133 : if (isSub) {
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 : .setMIFlags(MIFlags);
282 : } else {
283 : // Here we know that DestReg is not SP but we do not
284 : // know anything about BaseReg. t2ADDrr is an invalid
285 : // instruction is SP is used as the second argument, but
286 : // is fine if SP is the first argument. To be sure we
287 : // do not generate invalid encoding, put BaseReg first.
288 266 : BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg)
289 133 : .addReg(BaseReg)
290 133 : .addReg(DestReg, RegState::Kill)
291 133 : .add(predOps(Pred, PredReg))
292 133 : .add(condCodeOp())
293 : .setMIFlags(MIFlags);
294 : }
295 133 : return;
296 : }
297 : }
298 :
299 3730 : while (NumBytes) {
300 2307 : unsigned ThisVal = NumBytes;
301 : unsigned Opc = 0;
302 2307 : if (DestReg == ARM::SP && BaseReg != ARM::SP) {
303 : // mov sp, rn. Note t2MOVr cannot be used.
304 0 : BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
305 0 : .addReg(BaseReg)
306 : .setMIFlags(MIFlags)
307 0 : .add(predOps(ARMCC::AL));
308 : BaseReg = ARM::SP;
309 : continue;
310 : }
311 :
312 : bool HasCCOut = true;
313 2307 : if (BaseReg == ARM::SP) {
314 : // sub sp, sp, #imm7
315 1905 : if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) {
316 : assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?");
317 857 : Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
318 1714 : BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
319 857 : .addReg(BaseReg)
320 857 : .addImm(ThisVal / 4)
321 : .setMIFlags(MIFlags)
322 857 : .add(predOps(ARMCC::AL));
323 : NumBytes = 0;
324 : continue;
325 : }
326 :
327 : // sub rd, sp, so_imm
328 1048 : Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri;
329 1048 : if (ARM_AM::getT2SOImmVal(NumBytes) != -1) {
330 : NumBytes = 0;
331 : } else {
332 : // FIXME: Move this to ARMAddressingModes.h?
333 27 : unsigned RotAmt = countLeadingZeros(ThisVal);
334 27 : ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt);
335 27 : NumBytes &= ~ThisVal;
336 : assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&
337 : "Bit extraction didn't work?");
338 : }
339 : } else {
340 : assert(DestReg != ARM::SP && BaseReg != ARM::SP);
341 402 : Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri;
342 402 : if (ARM_AM::getT2SOImmVal(NumBytes) != -1) {
343 : NumBytes = 0;
344 0 : } else if (ThisVal < 4096) {
345 0 : Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12;
346 : HasCCOut = false;
347 : NumBytes = 0;
348 : } else {
349 : // 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 : assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&
354 : "Bit extraction didn't work?");
355 : }
356 : }
357 :
358 : // Build the new ADD / SUB.
359 2900 : MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
360 1450 : .addReg(BaseReg, RegState::Kill)
361 1450 : .addImm(ThisVal)
362 1450 : .add(predOps(ARMCC::AL))
363 1450 : .setMIFlags(MIFlags);
364 1450 : if (HasCCOut)
365 1450 : MIB.add(condCodeOp());
366 :
367 : BaseReg = DestReg;
368 : }
369 : }
370 :
371 : static unsigned
372 10 : negativeOffsetOpcode(unsigned opcode)
373 : {
374 10 : switch (opcode) {
375 : 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 7 : 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 :
385 0 : case ARM::t2LDRi8:
386 : case ARM::t2LDRHi8:
387 : case ARM::t2LDRBi8:
388 : case ARM::t2LDRSHi8:
389 : case ARM::t2LDRSBi8:
390 : case ARM::t2STRi8:
391 : case ARM::t2STRBi8:
392 : case ARM::t2STRHi8:
393 : case ARM::t2PLDi8:
394 0 : return opcode;
395 :
396 : default:
397 : break;
398 : }
399 :
400 0 : return 0;
401 : }
402 :
403 : static unsigned
404 3099 : positiveOffsetOpcode(unsigned opcode)
405 : {
406 3099 : switch (opcode) {
407 : 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 :
417 3099 : case ARM::t2LDRi12:
418 : case ARM::t2LDRHi12:
419 : case ARM::t2LDRBi12:
420 : case ARM::t2LDRSHi12:
421 : case ARM::t2LDRSBi12:
422 : case ARM::t2STRi12:
423 : case ARM::t2STRBi12:
424 : case ARM::t2STRHi12:
425 : case ARM::t2PLDi12:
426 3099 : return opcode;
427 :
428 : default:
429 : break;
430 : }
431 :
432 0 : return 0;
433 : }
434 :
435 : static unsigned
436 0 : immediateOffsetOpcode(unsigned opcode)
437 : {
438 0 : switch (opcode) {
439 : 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 :
449 0 : case ARM::t2LDRi12:
450 : case ARM::t2LDRHi12:
451 : case ARM::t2LDRBi12:
452 : case ARM::t2LDRSHi12:
453 : case ARM::t2LDRSBi12:
454 : case ARM::t2STRi12:
455 : case ARM::t2STRBi12:
456 : case ARM::t2STRHi12:
457 : case ARM::t2PLDi12:
458 : case ARM::t2LDRi8:
459 : case ARM::t2LDRHi8:
460 : case ARM::t2LDRBi8:
461 : case ARM::t2LDRSHi8:
462 : case ARM::t2LDRSBi8:
463 : case ARM::t2STRi8:
464 : case ARM::t2STRBi8:
465 : case ARM::t2STRHi8:
466 : case ARM::t2PLDi8:
467 0 : return opcode;
468 :
469 : default:
470 : break;
471 : }
472 :
473 0 : return 0;
474 : }
475 :
476 5525 : bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
477 : unsigned FrameReg, int &Offset,
478 : const ARMBaseInstrInfo &TII) {
479 5525 : unsigned Opcode = MI.getOpcode();
480 : const MCInstrDesc &Desc = MI.getDesc();
481 5525 : unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
482 : bool isSub = false;
483 :
484 : // Memory operands in inline assembly always use AddrModeT2_i12.
485 5525 : if (Opcode == ARM::INLINEASM)
486 : AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
487 :
488 5525 : if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
489 819 : Offset += MI.getOperand(FrameRegIdx+1).getImm();
490 :
491 : unsigned PredReg;
492 899 : if (Offset == 0 && getInstrPredicate(MI, PredReg) == ARMCC::AL &&
493 : !MI.definesRegister(ARM::CPSR)) {
494 : // Turn it into a move.
495 79 : MI.setDesc(TII.get(ARM::tMOVr));
496 158 : MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
497 : // Remove offset and remaining explicit predicate operands.
498 316 : do MI.RemoveOperand(FrameRegIdx+1);
499 316 : while (MI.getNumOperands() > FrameRegIdx+1);
500 79 : MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);
501 79 : MIB.add(predOps(ARMCC::AL));
502 : return true;
503 : }
504 :
505 : bool HasCCOut = Opcode != ARM::t2ADDri12;
506 :
507 740 : if (Offset < 0) {
508 18 : Offset = -Offset;
509 : isSub = true;
510 18 : MI.setDesc(TII.get(ARM::t2SUBri));
511 : } else {
512 722 : MI.setDesc(TII.get(ARM::t2ADDri));
513 : }
514 :
515 : // Common case: small offset, fits into instruction.
516 740 : if (ARM_AM::getT2SOImmVal(Offset) != -1) {
517 902 : MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
518 902 : MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
519 : // Add cc_out operand if the original instruction did not have one.
520 451 : if (!HasCCOut)
521 0 : MI.addOperand(MachineOperand::CreateReg(0, false));
522 451 : Offset = 0;
523 451 : return true;
524 : }
525 : // Another common case: imm12.
526 289 : if (Offset < 4096 &&
527 558 : (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {
528 279 : unsigned NewOpc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12;
529 279 : MI.setDesc(TII.get(NewOpc));
530 558 : MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
531 558 : MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
532 : // Remove the cc_out operand.
533 279 : if (HasCCOut)
534 279 : MI.RemoveOperand(MI.getNumOperands()-1);
535 279 : Offset = 0;
536 279 : return true;
537 : }
538 :
539 : // Otherwise, extract 8 adjacent bits from the immediate into this
540 : // t2ADDri/t2SUBri.
541 10 : unsigned RotAmt = countLeadingZeros<unsigned>(Offset);
542 10 : unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xff000000U, RotAmt);
543 :
544 : // We will handle these bits from offset, clear them.
545 10 : Offset &= ~ThisImmVal;
546 :
547 : assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
548 : "Bit extraction didn't work?");
549 20 : MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
550 : // Add cc_out operand if the original instruction did not have one.
551 10 : if (!HasCCOut)
552 0 : MI.addOperand(MachineOperand::CreateReg(0, false));
553 : } else {
554 : // AddrMode4 and AddrMode6 cannot handle any offset.
555 4706 : if (AddrMode == ARMII::AddrMode4 || AddrMode == ARMII::AddrMode6)
556 : return false;
557 :
558 : // AddrModeT2_so cannot handle any offset. If there is no offset
559 : // register then we change to an immediate version.
560 : unsigned NewOpc = Opcode;
561 3942 : if (AddrMode == ARMII::AddrModeT2_so) {
562 0 : unsigned OffsetReg = MI.getOperand(FrameRegIdx+1).getReg();
563 0 : if (OffsetReg != 0) {
564 0 : MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
565 0 : return Offset == 0;
566 : }
567 :
568 0 : MI.RemoveOperand(FrameRegIdx+1);
569 0 : MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
570 0 : NewOpc = immediateOffsetOpcode(Opcode);
571 : AddrMode = ARMII::AddrModeT2_i12;
572 : }
573 :
574 : unsigned NumBits = 0;
575 : unsigned Scale = 1;
576 3942 : if (AddrMode == ARMII::AddrModeT2_i8 || AddrMode == ARMII::AddrModeT2_i12) {
577 : // i8 supports only negative, and i12 supports only positive, so
578 : // based on Offset sign convert Opcode to the appropriate
579 : // instruction
580 3109 : Offset += MI.getOperand(FrameRegIdx+1).getImm();
581 3109 : if (Offset < 0) {
582 10 : NewOpc = negativeOffsetOpcode(Opcode);
583 : NumBits = 8;
584 : isSub = true;
585 10 : Offset = -Offset;
586 : } else {
587 3099 : NewOpc = positiveOffsetOpcode(Opcode);
588 : NumBits = 12;
589 : }
590 833 : } else if (AddrMode == ARMII::AddrMode5) {
591 : // VFP address mode.
592 798 : const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
593 1596 : int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
594 : if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
595 0 : InstrOffs *= -1;
596 : NumBits = 8;
597 : Scale = 4;
598 798 : Offset += InstrOffs * 4;
599 : assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
600 798 : if (Offset < 0) {
601 0 : Offset = -Offset;
602 : isSub = true;
603 : }
604 35 : } else if (AddrMode == ARMII::AddrMode5FP16) {
605 : // VFP address mode.
606 22 : const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
607 44 : int InstrOffs = ARM_AM::getAM5FP16Offset(OffOp.getImm());
608 : if (ARM_AM::getAM5FP16Op(OffOp.getImm()) == ARM_AM::sub)
609 0 : InstrOffs *= -1;
610 : NumBits = 8;
611 : Scale = 2;
612 22 : Offset += InstrOffs * 2;
613 : assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
614 22 : if (Offset < 0) {
615 0 : Offset = -Offset;
616 : isSub = true;
617 : }
618 13 : } else if (AddrMode == ARMII::AddrModeT2_i8s4) {
619 10 : Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4;
620 : NumBits = 10; // 8 bits scaled by 4
621 : // MCInst operand expects already scaled value.
622 : Scale = 1;
623 : assert((Offset & 3) == 0 && "Can't encode this offset!");
624 8 : } else if (AddrMode == ARMII::AddrModeT2_ldrex) {
625 16 : Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4;
626 : NumBits = 8; // 8 bits scaled by 4
627 : Scale = 4;
628 : assert((Offset & 3) == 0 && "Can't encode this offset!");
629 : } else {
630 0 : llvm_unreachable("Unsupported addressing mode!");
631 : }
632 :
633 3942 : if (NewOpc != Opcode)
634 10 : MI.setDesc(TII.get(NewOpc));
635 :
636 3942 : MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
637 :
638 : // Attempt to fold address computation
639 : // Common case: small offset, fits into instruction.
640 3942 : int ImmedOffset = Offset / Scale;
641 3942 : unsigned Mask = (1 << NumBits) - 1;
642 3942 : if ((unsigned)Offset <= Mask * Scale) {
643 : // Replace the FrameIndex with fp/sp
644 3564 : MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
645 3564 : if (isSub) {
646 10 : if (AddrMode == ARMII::AddrMode5)
647 : // FIXME: Not consistent.
648 0 : ImmedOffset |= 1 << NumBits;
649 : else
650 10 : ImmedOffset = -ImmedOffset;
651 : }
652 3564 : ImmOp.ChangeToImmediate(ImmedOffset);
653 3564 : Offset = 0;
654 3564 : return true;
655 : }
656 :
657 : // Otherwise, offset doesn't fit. Pull in what we can to simplify
658 378 : ImmedOffset = ImmedOffset & Mask;
659 378 : if (isSub) {
660 0 : if (AddrMode == ARMII::AddrMode5)
661 : // FIXME: Not consistent.
662 0 : ImmedOffset |= 1 << NumBits;
663 : else {
664 0 : ImmedOffset = -ImmedOffset;
665 0 : if (ImmedOffset == 0)
666 : // Change the opcode back if the encoded offset is zero.
667 0 : MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc)));
668 : }
669 : }
670 378 : ImmOp.ChangeToImmediate(ImmedOffset);
671 378 : Offset &= ~(Mask*Scale);
672 : }
673 :
674 388 : Offset = (isSub) ? -Offset : Offset;
675 388 : return Offset == 0;
676 : }
677 :
678 58638 : ARMCC::CondCodes llvm::getITInstrPredicate(const MachineInstr &MI,
679 : unsigned &PredReg) {
680 58638 : unsigned Opc = MI.getOpcode();
681 58638 : if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
682 : return ARMCC::AL;
683 57865 : return getInstrPredicate(MI, PredReg);
684 : }
|