blob: 9bca6a787da2ab08afd204ed334b774e48401516 [file] [log] [blame]
David Goodwin334c2642009-07-08 16:09:28 +00001//===- ARMBaseInstrInfo.cpp - ARM Instruction Information -----------*- C++ -*-===//
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 Base ARM implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARMBaseInstrInfo.h"
15#include "ARM.h"
16#include "ARMAddressingModes.h"
17#include "ARMGenInstrInfo.inc"
18#include "ARMMachineFunctionInfo.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/CodeGen/LiveVariables.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineJumpTableInfo.h"
24#include "llvm/Target/TargetAsmInfo.h"
25#include "llvm/Support/CommandLine.h"
Torok Edwinc25e7582009-07-11 20:10:48 +000026#include "llvm/Support/ErrorHandling.h"
David Goodwin334c2642009-07-08 16:09:28 +000027using namespace llvm;
28
29static cl::opt<bool>
30EnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden,
31 cl::desc("Enable ARM 2-addr to 3-addr conv"));
32
33static inline
34const MachineInstrBuilder &AddDefaultPred(const MachineInstrBuilder &MIB) {
35 return MIB.addImm((int64_t)ARMCC::AL).addReg(0);
36}
37
38static inline
39const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) {
40 return MIB.addReg(0);
41}
42
43ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget &STI)
44 : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)) {
45}
46
47MachineInstr *
48ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
49 MachineBasicBlock::iterator &MBBI,
50 LiveVariables *LV) const {
51 if (!EnableARM3Addr)
52 return NULL;
53
54 MachineInstr *MI = MBBI;
55 MachineFunction &MF = *MI->getParent()->getParent();
56 unsigned TSFlags = MI->getDesc().TSFlags;
57 bool isPre = false;
58 switch ((TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift) {
59 default: return NULL;
60 case ARMII::IndexModePre:
61 isPre = true;
62 break;
63 case ARMII::IndexModePost:
64 break;
65 }
66
67 // Try splitting an indexed load/store to an un-indexed one plus an add/sub
68 // operation.
69 unsigned MemOpc = getUnindexedOpcode(MI->getOpcode());
70 if (MemOpc == 0)
71 return NULL;
72
73 MachineInstr *UpdateMI = NULL;
74 MachineInstr *MemMI = NULL;
75 unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
76 const TargetInstrDesc &TID = MI->getDesc();
77 unsigned NumOps = TID.getNumOperands();
78 bool isLoad = !TID.mayStore();
79 const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0);
80 const MachineOperand &Base = MI->getOperand(2);
81 const MachineOperand &Offset = MI->getOperand(NumOps-3);
82 unsigned WBReg = WB.getReg();
83 unsigned BaseReg = Base.getReg();
84 unsigned OffReg = Offset.getReg();
85 unsigned OffImm = MI->getOperand(NumOps-2).getImm();
86 ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm();
87 switch (AddrMode) {
88 default:
89 assert(false && "Unknown indexed op!");
90 return NULL;
91 case ARMII::AddrMode2: {
92 bool isSub = ARM_AM::getAM2Op(OffImm) == ARM_AM::sub;
93 unsigned Amt = ARM_AM::getAM2Offset(OffImm);
94 if (OffReg == 0) {
Evan Chenge7cbe412009-07-08 21:03:57 +000095 if (ARM_AM::getSOImmVal(Amt) == -1)
David Goodwin334c2642009-07-08 16:09:28 +000096 // Can't encode it in a so_imm operand. This transformation will
97 // add more than 1 instruction. Abandon!
98 return NULL;
99 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
100 get(isSub ? getOpcode(ARMII::SUBri) :
101 getOpcode(ARMII::ADDri)), WBReg)
Evan Chenge7cbe412009-07-08 21:03:57 +0000102 .addReg(BaseReg).addImm(Amt)
David Goodwin334c2642009-07-08 16:09:28 +0000103 .addImm(Pred).addReg(0).addReg(0);
104 } else if (Amt != 0) {
105 ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm);
106 unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt);
107 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
108 get(isSub ? getOpcode(ARMII::SUBrs) :
109 getOpcode(ARMII::ADDrs)), WBReg)
110 .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc)
111 .addImm(Pred).addReg(0).addReg(0);
112 } else
113 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
114 get(isSub ? getOpcode(ARMII::SUBrr) :
115 getOpcode(ARMII::ADDrr)), WBReg)
116 .addReg(BaseReg).addReg(OffReg)
117 .addImm(Pred).addReg(0).addReg(0);
118 break;
119 }
120 case ARMII::AddrMode3 : {
121 bool isSub = ARM_AM::getAM3Op(OffImm) == ARM_AM::sub;
122 unsigned Amt = ARM_AM::getAM3Offset(OffImm);
123 if (OffReg == 0)
124 // Immediate is 8-bits. It's guaranteed to fit in a so_imm operand.
125 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
126 get(isSub ? getOpcode(ARMII::SUBri) :
127 getOpcode(ARMII::ADDri)), WBReg)
128 .addReg(BaseReg).addImm(Amt)
129 .addImm(Pred).addReg(0).addReg(0);
130 else
131 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
132 get(isSub ? getOpcode(ARMII::SUBrr) :
133 getOpcode(ARMII::ADDrr)), WBReg)
134 .addReg(BaseReg).addReg(OffReg)
135 .addImm(Pred).addReg(0).addReg(0);
136 break;
137 }
138 }
139
140 std::vector<MachineInstr*> NewMIs;
141 if (isPre) {
142 if (isLoad)
143 MemMI = BuildMI(MF, MI->getDebugLoc(),
144 get(MemOpc), MI->getOperand(0).getReg())
145 .addReg(WBReg).addReg(0).addImm(0).addImm(Pred);
146 else
147 MemMI = BuildMI(MF, MI->getDebugLoc(),
148 get(MemOpc)).addReg(MI->getOperand(1).getReg())
149 .addReg(WBReg).addReg(0).addImm(0).addImm(Pred);
150 NewMIs.push_back(MemMI);
151 NewMIs.push_back(UpdateMI);
152 } else {
153 if (isLoad)
154 MemMI = BuildMI(MF, MI->getDebugLoc(),
155 get(MemOpc), MI->getOperand(0).getReg())
156 .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred);
157 else
158 MemMI = BuildMI(MF, MI->getDebugLoc(),
159 get(MemOpc)).addReg(MI->getOperand(1).getReg())
160 .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred);
161 if (WB.isDead())
162 UpdateMI->getOperand(0).setIsDead();
163 NewMIs.push_back(UpdateMI);
164 NewMIs.push_back(MemMI);
165 }
166
167 // Transfer LiveVariables states, kill / dead info.
168 if (LV) {
169 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
170 MachineOperand &MO = MI->getOperand(i);
171 if (MO.isReg() && MO.getReg() &&
172 TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
173 unsigned Reg = MO.getReg();
174
175 LiveVariables::VarInfo &VI = LV->getVarInfo(Reg);
176 if (MO.isDef()) {
177 MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI;
178 if (MO.isDead())
179 LV->addVirtualRegisterDead(Reg, NewMI);
180 }
181 if (MO.isUse() && MO.isKill()) {
182 for (unsigned j = 0; j < 2; ++j) {
183 // Look at the two new MI's in reverse order.
184 MachineInstr *NewMI = NewMIs[j];
185 if (!NewMI->readsRegister(Reg))
186 continue;
187 LV->addVirtualRegisterKilled(Reg, NewMI);
188 if (VI.removeKill(MI))
189 VI.Kills.push_back(NewMI);
190 break;
191 }
192 }
193 }
194 }
195 }
196
197 MFI->insert(MBBI, NewMIs[1]);
198 MFI->insert(MBBI, NewMIs[0]);
199 return NewMIs[0];
200}
201
202// Branch analysis.
203bool
204ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
205 MachineBasicBlock *&FBB,
206 SmallVectorImpl<MachineOperand> &Cond,
207 bool AllowModify) const {
208 // If the block has no terminators, it just falls into the block after it.
209 MachineBasicBlock::iterator I = MBB.end();
210 if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
211 return false;
212
213 // Get the last instruction in the block.
214 MachineInstr *LastInst = I;
215
216 // If there is only one terminator instruction, process it.
217 unsigned LastOpc = LastInst->getOpcode();
218 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
219 if (LastOpc == getOpcode(ARMII::B)) {
220 TBB = LastInst->getOperand(0).getMBB();
221 return false;
222 }
223 if (LastOpc == getOpcode(ARMII::Bcc)) {
224 // Block ends with fall-through condbranch.
225 TBB = LastInst->getOperand(0).getMBB();
226 Cond.push_back(LastInst->getOperand(1));
227 Cond.push_back(LastInst->getOperand(2));
228 return false;
229 }
230 return true; // Can't handle indirect branch.
231 }
232
233 // Get the instruction before it if it is a terminator.
234 MachineInstr *SecondLastInst = I;
235
236 // If there are three terminators, we don't know what sort of block this is.
237 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I))
238 return true;
239
240 // If the block ends with ARMII::B and a ARMII::Bcc, handle it.
241 unsigned SecondLastOpc = SecondLastInst->getOpcode();
242 if ((SecondLastOpc == getOpcode(ARMII::Bcc)) &&
243 (LastOpc == getOpcode(ARMII::B))) {
244 TBB = SecondLastInst->getOperand(0).getMBB();
245 Cond.push_back(SecondLastInst->getOperand(1));
246 Cond.push_back(SecondLastInst->getOperand(2));
247 FBB = LastInst->getOperand(0).getMBB();
248 return false;
249 }
250
251 // If the block ends with two unconditional branches, handle it. The second
252 // one is not executed, so remove it.
253 if ((SecondLastOpc == getOpcode(ARMII::B)) &&
254 (LastOpc == getOpcode(ARMII::B))) {
255 TBB = SecondLastInst->getOperand(0).getMBB();
256 I = LastInst;
257 if (AllowModify)
258 I->eraseFromParent();
259 return false;
260 }
261
262 // ...likewise if it ends with a branch table followed by an unconditional
263 // branch. The branch folder can create these, and we must get rid of them for
264 // correctness of Thumb constant islands.
265 if (((SecondLastOpc == getOpcode(ARMII::BR_JTr)) ||
266 (SecondLastOpc == getOpcode(ARMII::BR_JTm)) ||
267 (SecondLastOpc == getOpcode(ARMII::BR_JTadd))) &&
268 (LastOpc == getOpcode(ARMII::B))) {
269 I = LastInst;
270 if (AllowModify)
271 I->eraseFromParent();
272 return true;
273 }
274
275 // Otherwise, can't handle this.
276 return true;
277}
278
279
280unsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
281 int BOpc = getOpcode(ARMII::B);
282 int BccOpc = getOpcode(ARMII::Bcc);
283
284 MachineBasicBlock::iterator I = MBB.end();
285 if (I == MBB.begin()) return 0;
286 --I;
287 if (I->getOpcode() != BOpc && I->getOpcode() != BccOpc)
288 return 0;
289
290 // Remove the branch.
291 I->eraseFromParent();
292
293 I = MBB.end();
294
295 if (I == MBB.begin()) return 1;
296 --I;
297 if (I->getOpcode() != BccOpc)
298 return 1;
299
300 // Remove the branch.
301 I->eraseFromParent();
302 return 2;
303}
304
305unsigned
306ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
307 MachineBasicBlock *FBB,
308 const SmallVectorImpl<MachineOperand> &Cond) const {
309 // FIXME this should probably have a DebugLoc argument
310 DebugLoc dl = DebugLoc::getUnknownLoc();
311 int BOpc = getOpcode(ARMII::B);
312 int BccOpc = getOpcode(ARMII::Bcc);
313
314 // Shouldn't be a fall through.
315 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
316 assert((Cond.size() == 2 || Cond.size() == 0) &&
317 "ARM branch conditions have two components!");
318
319 if (FBB == 0) {
320 if (Cond.empty()) // Unconditional branch?
321 BuildMI(&MBB, dl, get(BOpc)).addMBB(TBB);
322 else
323 BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB)
324 .addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
325 return 1;
326 }
327
328 // Two-way conditional branch.
329 BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB)
330 .addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
331 BuildMI(&MBB, dl, get(BOpc)).addMBB(FBB);
332 return 2;
333}
334
335bool ARMBaseInstrInfo::
336ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
337 ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm();
338 Cond[0].setImm(ARMCC::getOppositeCondition(CC));
339 return false;
340}
341
David Goodwin334c2642009-07-08 16:09:28 +0000342bool ARMBaseInstrInfo::
343PredicateInstruction(MachineInstr *MI,
344 const SmallVectorImpl<MachineOperand> &Pred) const {
345 unsigned Opc = MI->getOpcode();
346 if (Opc == getOpcode(ARMII::B)) {
347 MI->setDesc(get(getOpcode(ARMII::Bcc)));
348 MI->addOperand(MachineOperand::CreateImm(Pred[0].getImm()));
349 MI->addOperand(MachineOperand::CreateReg(Pred[1].getReg(), false));
350 return true;
351 }
352
353 int PIdx = MI->findFirstPredOperandIdx();
354 if (PIdx != -1) {
355 MachineOperand &PMO = MI->getOperand(PIdx);
356 PMO.setImm(Pred[0].getImm());
357 MI->getOperand(PIdx+1).setReg(Pred[1].getReg());
358 return true;
359 }
360 return false;
361}
362
363bool ARMBaseInstrInfo::
364SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
365 const SmallVectorImpl<MachineOperand> &Pred2) const {
366 if (Pred1.size() > 2 || Pred2.size() > 2)
367 return false;
368
369 ARMCC::CondCodes CC1 = (ARMCC::CondCodes)Pred1[0].getImm();
370 ARMCC::CondCodes CC2 = (ARMCC::CondCodes)Pred2[0].getImm();
371 if (CC1 == CC2)
372 return true;
373
374 switch (CC1) {
375 default:
376 return false;
377 case ARMCC::AL:
378 return true;
379 case ARMCC::HS:
380 return CC2 == ARMCC::HI;
381 case ARMCC::LS:
382 return CC2 == ARMCC::LO || CC2 == ARMCC::EQ;
383 case ARMCC::GE:
384 return CC2 == ARMCC::GT;
385 case ARMCC::LE:
386 return CC2 == ARMCC::LT;
387 }
388}
389
390bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI,
391 std::vector<MachineOperand> &Pred) const {
392 const TargetInstrDesc &TID = MI->getDesc();
393 if (!TID.getImplicitDefs() && !TID.hasOptionalDef())
394 return false;
395
396 bool Found = false;
397 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
398 const MachineOperand &MO = MI->getOperand(i);
399 if (MO.isReg() && MO.getReg() == ARM::CPSR) {
400 Pred.push_back(MO);
401 Found = true;
402 }
403 }
404
405 return Found;
406}
407
408
409/// FIXME: Works around a gcc miscompilation with -fstrict-aliasing
410static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
411 unsigned JTI) DISABLE_INLINE;
412static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
413 unsigned JTI) {
414 return JT[JTI].MBBs.size();
415}
416
417/// GetInstSize - Return the size of the specified MachineInstr.
418///
419unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
420 const MachineBasicBlock &MBB = *MI->getParent();
421 const MachineFunction *MF = MBB.getParent();
422 const TargetAsmInfo *TAI = MF->getTarget().getTargetAsmInfo();
423
424 // Basic size info comes from the TSFlags field.
425 const TargetInstrDesc &TID = MI->getDesc();
426 unsigned TSFlags = TID.TSFlags;
427
428 switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
429 default: {
430 // If this machine instr is an inline asm, measure it.
431 if (MI->getOpcode() == ARM::INLINEASM)
432 return TAI->getInlineAsmLength(MI->getOperand(0).getSymbolName());
433 if (MI->isLabel())
434 return 0;
435 switch (MI->getOpcode()) {
436 default:
Torok Edwinc25e7582009-07-11 20:10:48 +0000437 LLVM_UNREACHABLE("Unknown or unset size field for instr!");
David Goodwin334c2642009-07-08 16:09:28 +0000438 case TargetInstrInfo::IMPLICIT_DEF:
439 case TargetInstrInfo::DECLARE:
440 case TargetInstrInfo::DBG_LABEL:
441 case TargetInstrInfo::EH_LABEL:
442 return 0;
443 }
444 break;
445 }
446 case ARMII::Size8Bytes: return 8; // Arm instruction x 2.
447 case ARMII::Size4Bytes: return 4; // Arm instruction.
448 case ARMII::Size2Bytes: return 2; // Thumb instruction.
449 case ARMII::SizeSpecial: {
450 switch (MI->getOpcode()) {
451 case ARM::CONSTPOOL_ENTRY:
452 // If this machine instr is a constant pool entry, its size is recorded as
453 // operand #2.
454 return MI->getOperand(2).getImm();
455 case ARM::Int_eh_sjlj_setjmp: return 12;
456 case ARM::BR_JTr:
457 case ARM::BR_JTm:
458 case ARM::BR_JTadd:
459 case ARM::t2BR_JTr:
460 case ARM::t2BR_JTm:
461 case ARM::t2BR_JTadd:
462 case ARM::tBR_JTr: {
463 // These are jumptable branches, i.e. a branch followed by an inlined
464 // jumptable. The size is 4 + 4 * number of entries.
465 unsigned NumOps = TID.getNumOperands();
466 MachineOperand JTOP =
467 MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2));
468 unsigned JTI = JTOP.getIndex();
469 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
470 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
471 assert(JTI < JT.size());
472 // Thumb instructions are 2 byte aligned, but JT entries are 4 byte
473 // 4 aligned. The assembler / linker may add 2 byte padding just before
474 // the JT entries. The size does not include this padding; the
475 // constant islands pass does separate bookkeeping for it.
476 // FIXME: If we know the size of the function is less than (1 << 16) *2
477 // bytes, we can use 16-bit entries instead. Then there won't be an
478 // alignment issue.
479 return getNumJTEntries(JT, JTI) * 4 +
480 ((MI->getOpcode()==ARM::tBR_JTr) ? 2 : 4);
481 }
482 default:
483 // Otherwise, pseudo-instruction sizes are zero.
484 return 0;
485 }
486 }
487 }
488 return 0; // Not reached
489}
490
491/// Return true if the instruction is a register to register move and
492/// leave the source and dest operands in the passed parameters.
493///
494bool
495ARMBaseInstrInfo::isMoveInstr(const MachineInstr &MI,
496 unsigned &SrcReg, unsigned &DstReg,
497 unsigned& SrcSubIdx, unsigned& DstSubIdx) const {
498 SrcSubIdx = DstSubIdx = 0; // No sub-registers.
499
500 unsigned oc = MI.getOpcode();
501 if ((oc == getOpcode(ARMII::FCPYS)) ||
502 (oc == getOpcode(ARMII::FCPYD)) ||
503 (oc == getOpcode(ARMII::VMOVD)) ||
504 (oc == getOpcode(ARMII::VMOVQ))) {
505 SrcReg = MI.getOperand(1).getReg();
506 DstReg = MI.getOperand(0).getReg();
507 return true;
508 }
509 else if (oc == getOpcode(ARMII::MOVr)) {
510 assert(MI.getDesc().getNumOperands() >= 2 &&
511 MI.getOperand(0).isReg() &&
512 MI.getOperand(1).isReg() &&
513 "Invalid ARM MOV instruction");
514 SrcReg = MI.getOperand(1).getReg();
515 DstReg = MI.getOperand(0).getReg();
516 return true;
517 }
518
519 return false;
520}
521
522unsigned
523ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
524 int &FrameIndex) const {
525 unsigned oc = MI->getOpcode();
526 if (oc == getOpcode(ARMII::LDR)) {
527 if (MI->getOperand(1).isFI() &&
528 MI->getOperand(2).isReg() &&
529 MI->getOperand(3).isImm() &&
530 MI->getOperand(2).getReg() == 0 &&
531 MI->getOperand(3).getImm() == 0) {
532 FrameIndex = MI->getOperand(1).getIndex();
533 return MI->getOperand(0).getReg();
534 }
535 }
536 else if ((oc == getOpcode(ARMII::FLDD)) ||
537 (oc == getOpcode(ARMII::FLDS))) {
538 if (MI->getOperand(1).isFI() &&
539 MI->getOperand(2).isImm() &&
540 MI->getOperand(2).getImm() == 0) {
541 FrameIndex = MI->getOperand(1).getIndex();
542 return MI->getOperand(0).getReg();
543 }
544 }
545
546 return 0;
547}
548
549unsigned
550ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
551 int &FrameIndex) const {
552 unsigned oc = MI->getOpcode();
553 if (oc == getOpcode(ARMII::STR)) {
554 if (MI->getOperand(1).isFI() &&
555 MI->getOperand(2).isReg() &&
556 MI->getOperand(3).isImm() &&
557 MI->getOperand(2).getReg() == 0 &&
558 MI->getOperand(3).getImm() == 0) {
559 FrameIndex = MI->getOperand(1).getIndex();
560 return MI->getOperand(0).getReg();
561 }
562 }
563 else if ((oc == getOpcode(ARMII::FSTD)) ||
564 (oc == getOpcode(ARMII::FSTS))) {
565 if (MI->getOperand(1).isFI() &&
566 MI->getOperand(2).isImm() &&
567 MI->getOperand(2).getImm() == 0) {
568 FrameIndex = MI->getOperand(1).getIndex();
569 return MI->getOperand(0).getReg();
570 }
571 }
572
573 return 0;
574}
575
576bool
577ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
578 MachineBasicBlock::iterator I,
579 unsigned DestReg, unsigned SrcReg,
580 const TargetRegisterClass *DestRC,
581 const TargetRegisterClass *SrcRC) const {
582 DebugLoc DL = DebugLoc::getUnknownLoc();
583 if (I != MBB.end()) DL = I->getDebugLoc();
584
585 if (DestRC != SrcRC) {
586 // Not yet supported!
587 return false;
588 }
589
590 if (DestRC == ARM::GPRRegisterClass)
Evan Chengdd6f6322009-07-11 06:37:27 +0000591 AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::MOVr)),
592 DestReg).addReg(SrcReg)));
David Goodwin334c2642009-07-08 16:09:28 +0000593 else if (DestRC == ARM::SPRRegisterClass)
594 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FCPYS)), DestReg)
595 .addReg(SrcReg));
596 else if (DestRC == ARM::DPRRegisterClass)
597 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FCPYD)), DestReg)
598 .addReg(SrcReg));
599 else if (DestRC == ARM::QPRRegisterClass)
600 BuildMI(MBB, I, DL, get(getOpcode(ARMII::VMOVQ)), DestReg).addReg(SrcReg);
601 else
602 return false;
603
604 return true;
605}
606
607void ARMBaseInstrInfo::
608storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
609 unsigned SrcReg, bool isKill, int FI,
610 const TargetRegisterClass *RC) const {
611 DebugLoc DL = DebugLoc::getUnknownLoc();
612 if (I != MBB.end()) DL = I->getDebugLoc();
613
614 if (RC == ARM::GPRRegisterClass) {
615 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::STR)))
616 .addReg(SrcReg, getKillRegState(isKill))
617 .addFrameIndex(FI).addReg(0).addImm(0));
618 } else if (RC == ARM::DPRRegisterClass) {
619 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FSTD)))
620 .addReg(SrcReg, getKillRegState(isKill))
621 .addFrameIndex(FI).addImm(0));
622 } else {
623 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
624 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FSTS)))
625 .addReg(SrcReg, getKillRegState(isKill))
626 .addFrameIndex(FI).addImm(0));
627 }
628}
629
630void
631ARMBaseInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
632 bool isKill,
633 SmallVectorImpl<MachineOperand> &Addr,
634 const TargetRegisterClass *RC,
635 SmallVectorImpl<MachineInstr*> &NewMIs) const{
636 DebugLoc DL = DebugLoc::getUnknownLoc();
637 unsigned Opc = 0;
638 if (RC == ARM::GPRRegisterClass) {
639 Opc = getOpcode(ARMII::STR);
640 } else if (RC == ARM::DPRRegisterClass) {
641 Opc = getOpcode(ARMII::FSTD);
642 } else {
643 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
644 Opc = getOpcode(ARMII::FSTS);
645 }
646
647 MachineInstrBuilder MIB =
648 BuildMI(MF, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill));
649 for (unsigned i = 0, e = Addr.size(); i != e; ++i)
650 MIB.addOperand(Addr[i]);
651 AddDefaultPred(MIB);
652 NewMIs.push_back(MIB);
653 return;
654}
655
656void ARMBaseInstrInfo::
657loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
658 unsigned DestReg, int FI,
659 const TargetRegisterClass *RC) const {
660 DebugLoc DL = DebugLoc::getUnknownLoc();
661 if (I != MBB.end()) DL = I->getDebugLoc();
662
663 if (RC == ARM::GPRRegisterClass) {
664 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::LDR)), DestReg)
665 .addFrameIndex(FI).addReg(0).addImm(0));
666 } else if (RC == ARM::DPRRegisterClass) {
667 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FLDD)), DestReg)
668 .addFrameIndex(FI).addImm(0));
669 } else {
670 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
671 AddDefaultPred(BuildMI(MBB, I, DL, get(getOpcode(ARMII::FLDS)), DestReg)
672 .addFrameIndex(FI).addImm(0));
673 }
674}
675
676void ARMBaseInstrInfo::
677loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
678 SmallVectorImpl<MachineOperand> &Addr,
679 const TargetRegisterClass *RC,
680 SmallVectorImpl<MachineInstr*> &NewMIs) const {
681 DebugLoc DL = DebugLoc::getUnknownLoc();
682 unsigned Opc = 0;
683 if (RC == ARM::GPRRegisterClass) {
684 Opc = getOpcode(ARMII::LDR);
685 } else if (RC == ARM::DPRRegisterClass) {
686 Opc = getOpcode(ARMII::FLDD);
687 } else {
688 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
689 Opc = getOpcode(ARMII::FLDS);
690 }
691
692 MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
693 for (unsigned i = 0, e = Addr.size(); i != e; ++i)
694 MIB.addOperand(Addr[i]);
695 AddDefaultPred(MIB);
696 NewMIs.push_back(MIB);
697 return;
698}
699
700MachineInstr *ARMBaseInstrInfo::
701foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
702 const SmallVectorImpl<unsigned> &Ops, int FI) const {
703 if (Ops.size() != 1) return NULL;
704
705 unsigned OpNum = Ops[0];
706 unsigned Opc = MI->getOpcode();
707 MachineInstr *NewMI = NULL;
708 if (Opc == getOpcode(ARMII::MOVr)) {
709 // If it is updating CPSR, then it cannot be folded.
710 if (MI->getOperand(4).getReg() != ARM::CPSR) {
711 unsigned Pred = MI->getOperand(2).getImm();
712 unsigned PredReg = MI->getOperand(3).getReg();
713 if (OpNum == 0) { // move -> store
714 unsigned SrcReg = MI->getOperand(1).getReg();
715 bool isKill = MI->getOperand(1).isKill();
716 bool isUndef = MI->getOperand(1).isUndef();
717 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::STR)))
718 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef))
719 .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
720 } else { // move -> load
721 unsigned DstReg = MI->getOperand(0).getReg();
722 bool isDead = MI->getOperand(0).isDead();
723 bool isUndef = MI->getOperand(0).isUndef();
724 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::LDR)))
725 .addReg(DstReg,
726 RegState::Define |
727 getDeadRegState(isDead) |
728 getUndefRegState(isUndef))
729 .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
730 }
731 }
732 }
733 else if (Opc == getOpcode(ARMII::FCPYS)) {
734 unsigned Pred = MI->getOperand(2).getImm();
735 unsigned PredReg = MI->getOperand(3).getReg();
736 if (OpNum == 0) { // move -> store
737 unsigned SrcReg = MI->getOperand(1).getReg();
738 bool isKill = MI->getOperand(1).isKill();
739 bool isUndef = MI->getOperand(1).isUndef();
740 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::FSTS)))
741 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef))
742 .addFrameIndex(FI)
743 .addImm(0).addImm(Pred).addReg(PredReg);
744 } else { // move -> load
745 unsigned DstReg = MI->getOperand(0).getReg();
746 bool isDead = MI->getOperand(0).isDead();
747 bool isUndef = MI->getOperand(0).isUndef();
748 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::FLDS)))
749 .addReg(DstReg,
750 RegState::Define |
751 getDeadRegState(isDead) |
752 getUndefRegState(isUndef))
753 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
754 }
755 }
756 else if (Opc == getOpcode(ARMII::FCPYD)) {
757 unsigned Pred = MI->getOperand(2).getImm();
758 unsigned PredReg = MI->getOperand(3).getReg();
759 if (OpNum == 0) { // move -> store
760 unsigned SrcReg = MI->getOperand(1).getReg();
761 bool isKill = MI->getOperand(1).isKill();
762 bool isUndef = MI->getOperand(1).isUndef();
763 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::FSTD)))
764 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef))
765 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
766 } else { // move -> load
767 unsigned DstReg = MI->getOperand(0).getReg();
768 bool isDead = MI->getOperand(0).isDead();
769 bool isUndef = MI->getOperand(0).isUndef();
770 NewMI = BuildMI(MF, MI->getDebugLoc(), get(getOpcode(ARMII::FLDD)))
771 .addReg(DstReg,
772 RegState::Define |
773 getDeadRegState(isDead) |
774 getUndefRegState(isUndef))
775 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
776 }
777 }
778
779 return NewMI;
780}
781
782MachineInstr*
783ARMBaseInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
784 MachineInstr* MI,
785 const SmallVectorImpl<unsigned> &Ops,
786 MachineInstr* LoadMI) const {
787 return 0;
788}
789
790bool
791ARMBaseInstrInfo::canFoldMemoryOperand(const MachineInstr *MI,
792 const SmallVectorImpl<unsigned> &Ops) const {
793 if (Ops.size() != 1) return false;
794
795 unsigned Opc = MI->getOpcode();
796 if (Opc == getOpcode(ARMII::MOVr)) {
797 // If it is updating CPSR, then it cannot be folded.
798 return MI->getOperand(4).getReg() != ARM::CPSR;
799 }
800 else if ((Opc == getOpcode(ARMII::FCPYS)) ||
801 (Opc == getOpcode(ARMII::FCPYD))) {
802 return true;
803 }
804 else if ((Opc == getOpcode(ARMII::VMOVD)) ||
805 (Opc == getOpcode(ARMII::VMOVQ))) {
806 return false; // FIXME
807 }
808
809 return false;
810}