blob: 6e1f5580c2f4939a60c24029049478e84b3cc5f1 [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
Evan Cheng5ca53a72009-07-27 18:20:05 +000033ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget &sti)
34 : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)),
35 STI(sti) {
David Goodwin334c2642009-07-08 16:09:28 +000036}
37
38MachineInstr *
39ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
40 MachineBasicBlock::iterator &MBBI,
41 LiveVariables *LV) const {
Evan Cheng78703dd2009-07-27 18:44:00 +000042 // FIXME: Thumb2 support.
43
David Goodwin334c2642009-07-08 16:09:28 +000044 if (!EnableARM3Addr)
45 return NULL;
46
47 MachineInstr *MI = MBBI;
48 MachineFunction &MF = *MI->getParent()->getParent();
49 unsigned TSFlags = MI->getDesc().TSFlags;
50 bool isPre = false;
51 switch ((TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift) {
52 default: return NULL;
53 case ARMII::IndexModePre:
54 isPre = true;
55 break;
56 case ARMII::IndexModePost:
57 break;
58 }
59
60 // Try splitting an indexed load/store to an un-indexed one plus an add/sub
61 // operation.
62 unsigned MemOpc = getUnindexedOpcode(MI->getOpcode());
63 if (MemOpc == 0)
64 return NULL;
65
66 MachineInstr *UpdateMI = NULL;
67 MachineInstr *MemMI = NULL;
68 unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
69 const TargetInstrDesc &TID = MI->getDesc();
70 unsigned NumOps = TID.getNumOperands();
71 bool isLoad = !TID.mayStore();
72 const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0);
73 const MachineOperand &Base = MI->getOperand(2);
74 const MachineOperand &Offset = MI->getOperand(NumOps-3);
75 unsigned WBReg = WB.getReg();
76 unsigned BaseReg = Base.getReg();
77 unsigned OffReg = Offset.getReg();
78 unsigned OffImm = MI->getOperand(NumOps-2).getImm();
79 ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm();
80 switch (AddrMode) {
81 default:
82 assert(false && "Unknown indexed op!");
83 return NULL;
84 case ARMII::AddrMode2: {
85 bool isSub = ARM_AM::getAM2Op(OffImm) == ARM_AM::sub;
86 unsigned Amt = ARM_AM::getAM2Offset(OffImm);
87 if (OffReg == 0) {
Evan Chenge7cbe412009-07-08 21:03:57 +000088 if (ARM_AM::getSOImmVal(Amt) == -1)
David Goodwin334c2642009-07-08 16:09:28 +000089 // Can't encode it in a so_imm operand. This transformation will
90 // add more than 1 instruction. Abandon!
91 return NULL;
92 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +000093 get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
Evan Chenge7cbe412009-07-08 21:03:57 +000094 .addReg(BaseReg).addImm(Amt)
David Goodwin334c2642009-07-08 16:09:28 +000095 .addImm(Pred).addReg(0).addReg(0);
96 } else if (Amt != 0) {
97 ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm);
98 unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt);
99 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000100 get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg)
David Goodwin334c2642009-07-08 16:09:28 +0000101 .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc)
102 .addImm(Pred).addReg(0).addReg(0);
103 } else
104 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000105 get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
David Goodwin334c2642009-07-08 16:09:28 +0000106 .addReg(BaseReg).addReg(OffReg)
107 .addImm(Pred).addReg(0).addReg(0);
108 break;
109 }
110 case ARMII::AddrMode3 : {
111 bool isSub = ARM_AM::getAM3Op(OffImm) == ARM_AM::sub;
112 unsigned Amt = ARM_AM::getAM3Offset(OffImm);
113 if (OffReg == 0)
114 // Immediate is 8-bits. It's guaranteed to fit in a so_imm operand.
115 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000116 get(isSub ? ARM::SUBri : ARM::ADDri), WBReg)
David Goodwin334c2642009-07-08 16:09:28 +0000117 .addReg(BaseReg).addImm(Amt)
118 .addImm(Pred).addReg(0).addReg(0);
119 else
120 UpdateMI = BuildMI(MF, MI->getDebugLoc(),
Evan Cheng78703dd2009-07-27 18:44:00 +0000121 get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg)
David Goodwin334c2642009-07-08 16:09:28 +0000122 .addReg(BaseReg).addReg(OffReg)
123 .addImm(Pred).addReg(0).addReg(0);
124 break;
125 }
126 }
127
128 std::vector<MachineInstr*> NewMIs;
129 if (isPre) {
130 if (isLoad)
131 MemMI = BuildMI(MF, MI->getDebugLoc(),
132 get(MemOpc), MI->getOperand(0).getReg())
133 .addReg(WBReg).addReg(0).addImm(0).addImm(Pred);
134 else
135 MemMI = BuildMI(MF, MI->getDebugLoc(),
136 get(MemOpc)).addReg(MI->getOperand(1).getReg())
137 .addReg(WBReg).addReg(0).addImm(0).addImm(Pred);
138 NewMIs.push_back(MemMI);
139 NewMIs.push_back(UpdateMI);
140 } else {
141 if (isLoad)
142 MemMI = BuildMI(MF, MI->getDebugLoc(),
143 get(MemOpc), MI->getOperand(0).getReg())
144 .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred);
145 else
146 MemMI = BuildMI(MF, MI->getDebugLoc(),
147 get(MemOpc)).addReg(MI->getOperand(1).getReg())
148 .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred);
149 if (WB.isDead())
150 UpdateMI->getOperand(0).setIsDead();
151 NewMIs.push_back(UpdateMI);
152 NewMIs.push_back(MemMI);
153 }
154
155 // Transfer LiveVariables states, kill / dead info.
156 if (LV) {
157 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
158 MachineOperand &MO = MI->getOperand(i);
159 if (MO.isReg() && MO.getReg() &&
160 TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
161 unsigned Reg = MO.getReg();
162
163 LiveVariables::VarInfo &VI = LV->getVarInfo(Reg);
164 if (MO.isDef()) {
165 MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI;
166 if (MO.isDead())
167 LV->addVirtualRegisterDead(Reg, NewMI);
168 }
169 if (MO.isUse() && MO.isKill()) {
170 for (unsigned j = 0; j < 2; ++j) {
171 // Look at the two new MI's in reverse order.
172 MachineInstr *NewMI = NewMIs[j];
173 if (!NewMI->readsRegister(Reg))
174 continue;
175 LV->addVirtualRegisterKilled(Reg, NewMI);
176 if (VI.removeKill(MI))
177 VI.Kills.push_back(NewMI);
178 break;
179 }
180 }
181 }
182 }
183 }
184
185 MFI->insert(MBBI, NewMIs[1]);
186 MFI->insert(MBBI, NewMIs[0]);
187 return NewMIs[0];
188}
189
190// Branch analysis.
191bool
192ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
193 MachineBasicBlock *&FBB,
194 SmallVectorImpl<MachineOperand> &Cond,
195 bool AllowModify) const {
196 // If the block has no terminators, it just falls into the block after it.
197 MachineBasicBlock::iterator I = MBB.end();
198 if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
199 return false;
200
201 // Get the last instruction in the block.
202 MachineInstr *LastInst = I;
203
204 // If there is only one terminator instruction, process it.
205 unsigned LastOpc = LastInst->getOpcode();
206 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
Evan Cheng5ca53a72009-07-27 18:20:05 +0000207 if (isUncondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000208 TBB = LastInst->getOperand(0).getMBB();
209 return false;
210 }
Evan Cheng5ca53a72009-07-27 18:20:05 +0000211 if (isCondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000212 // Block ends with fall-through condbranch.
213 TBB = LastInst->getOperand(0).getMBB();
214 Cond.push_back(LastInst->getOperand(1));
215 Cond.push_back(LastInst->getOperand(2));
216 return false;
217 }
218 return true; // Can't handle indirect branch.
219 }
220
221 // Get the instruction before it if it is a terminator.
222 MachineInstr *SecondLastInst = I;
223
224 // If there are three terminators, we don't know what sort of block this is.
225 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I))
226 return true;
227
Evan Cheng5ca53a72009-07-27 18:20:05 +0000228 // If the block ends with a B and a Bcc, handle it.
David Goodwin334c2642009-07-08 16:09:28 +0000229 unsigned SecondLastOpc = SecondLastInst->getOpcode();
Evan Cheng5ca53a72009-07-27 18:20:05 +0000230 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000231 TBB = SecondLastInst->getOperand(0).getMBB();
232 Cond.push_back(SecondLastInst->getOperand(1));
233 Cond.push_back(SecondLastInst->getOperand(2));
234 FBB = LastInst->getOperand(0).getMBB();
235 return false;
236 }
237
238 // If the block ends with two unconditional branches, handle it. The second
239 // one is not executed, so remove it.
Evan Cheng5ca53a72009-07-27 18:20:05 +0000240 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000241 TBB = SecondLastInst->getOperand(0).getMBB();
242 I = LastInst;
243 if (AllowModify)
244 I->eraseFromParent();
245 return false;
246 }
247
248 // ...likewise if it ends with a branch table followed by an unconditional
249 // branch. The branch folder can create these, and we must get rid of them for
250 // correctness of Thumb constant islands.
Evan Cheng83e0e362009-07-27 18:25:24 +0000251 if (isJumpTableBranchOpcode(SecondLastOpc) &&
Evan Cheng5ca53a72009-07-27 18:20:05 +0000252 isUncondBranchOpcode(LastOpc)) {
David Goodwin334c2642009-07-08 16:09:28 +0000253 I = LastInst;
254 if (AllowModify)
255 I->eraseFromParent();
256 return true;
257 }
258
259 // Otherwise, can't handle this.
260 return true;
261}
262
263
264unsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
David Goodwin334c2642009-07-08 16:09:28 +0000265 MachineBasicBlock::iterator I = MBB.end();
266 if (I == MBB.begin()) return 0;
267 --I;
Evan Cheng5ca53a72009-07-27 18:20:05 +0000268 if (!isUncondBranchOpcode(I->getOpcode()) &&
269 !isCondBranchOpcode(I->getOpcode()))
David Goodwin334c2642009-07-08 16:09:28 +0000270 return 0;
271
272 // Remove the branch.
273 I->eraseFromParent();
274
275 I = MBB.end();
276
277 if (I == MBB.begin()) return 1;
278 --I;
Evan Cheng5ca53a72009-07-27 18:20:05 +0000279 if (!isCondBranchOpcode(I->getOpcode()))
David Goodwin334c2642009-07-08 16:09:28 +0000280 return 1;
281
282 // Remove the branch.
283 I->eraseFromParent();
284 return 2;
285}
286
287unsigned
288ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
289 MachineBasicBlock *FBB,
290 const SmallVectorImpl<MachineOperand> &Cond) const {
291 // FIXME this should probably have a DebugLoc argument
292 DebugLoc dl = DebugLoc::getUnknownLoc();
Evan Cheng5ca53a72009-07-27 18:20:05 +0000293 int BOpc = !STI.isThumb()
294 ? ARM::B : (STI.isThumb2() ? ARM::t2B : ARM::tB);
295 int BccOpc = !STI.isThumb()
296 ? ARM::Bcc : (STI.isThumb2() ? ARM::t2Bcc : ARM::tBcc);
David Goodwin334c2642009-07-08 16:09:28 +0000297
298 // Shouldn't be a fall through.
299 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
300 assert((Cond.size() == 2 || Cond.size() == 0) &&
301 "ARM branch conditions have two components!");
302
303 if (FBB == 0) {
304 if (Cond.empty()) // Unconditional branch?
305 BuildMI(&MBB, dl, get(BOpc)).addMBB(TBB);
306 else
307 BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB)
308 .addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
309 return 1;
310 }
311
312 // Two-way conditional branch.
313 BuildMI(&MBB, dl, get(BccOpc)).addMBB(TBB)
314 .addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
315 BuildMI(&MBB, dl, get(BOpc)).addMBB(FBB);
316 return 2;
317}
318
319bool ARMBaseInstrInfo::
320ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
321 ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm();
322 Cond[0].setImm(ARMCC::getOppositeCondition(CC));
323 return false;
324}
325
David Goodwin334c2642009-07-08 16:09:28 +0000326bool ARMBaseInstrInfo::
327PredicateInstruction(MachineInstr *MI,
328 const SmallVectorImpl<MachineOperand> &Pred) const {
329 unsigned Opc = MI->getOpcode();
Evan Cheng5ca53a72009-07-27 18:20:05 +0000330 if (isUncondBranchOpcode(Opc)) {
331 MI->setDesc(get(getMatchingCondBranchOpcode(Opc)));
David Goodwin334c2642009-07-08 16:09:28 +0000332 MI->addOperand(MachineOperand::CreateImm(Pred[0].getImm()));
333 MI->addOperand(MachineOperand::CreateReg(Pred[1].getReg(), false));
334 return true;
335 }
336
337 int PIdx = MI->findFirstPredOperandIdx();
338 if (PIdx != -1) {
339 MachineOperand &PMO = MI->getOperand(PIdx);
340 PMO.setImm(Pred[0].getImm());
341 MI->getOperand(PIdx+1).setReg(Pred[1].getReg());
342 return true;
343 }
344 return false;
345}
346
347bool ARMBaseInstrInfo::
348SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
349 const SmallVectorImpl<MachineOperand> &Pred2) const {
350 if (Pred1.size() > 2 || Pred2.size() > 2)
351 return false;
352
353 ARMCC::CondCodes CC1 = (ARMCC::CondCodes)Pred1[0].getImm();
354 ARMCC::CondCodes CC2 = (ARMCC::CondCodes)Pred2[0].getImm();
355 if (CC1 == CC2)
356 return true;
357
358 switch (CC1) {
359 default:
360 return false;
361 case ARMCC::AL:
362 return true;
363 case ARMCC::HS:
364 return CC2 == ARMCC::HI;
365 case ARMCC::LS:
366 return CC2 == ARMCC::LO || CC2 == ARMCC::EQ;
367 case ARMCC::GE:
368 return CC2 == ARMCC::GT;
369 case ARMCC::LE:
370 return CC2 == ARMCC::LT;
371 }
372}
373
374bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI,
375 std::vector<MachineOperand> &Pred) const {
376 const TargetInstrDesc &TID = MI->getDesc();
377 if (!TID.getImplicitDefs() && !TID.hasOptionalDef())
378 return false;
379
380 bool Found = false;
381 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
382 const MachineOperand &MO = MI->getOperand(i);
383 if (MO.isReg() && MO.getReg() == ARM::CPSR) {
384 Pred.push_back(MO);
385 Found = true;
386 }
387 }
388
389 return Found;
390}
391
392
393/// FIXME: Works around a gcc miscompilation with -fstrict-aliasing
394static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
395 unsigned JTI) DISABLE_INLINE;
396static unsigned getNumJTEntries(const std::vector<MachineJumpTableEntry> &JT,
397 unsigned JTI) {
398 return JT[JTI].MBBs.size();
399}
400
401/// GetInstSize - Return the size of the specified MachineInstr.
402///
403unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
404 const MachineBasicBlock &MBB = *MI->getParent();
405 const MachineFunction *MF = MBB.getParent();
406 const TargetAsmInfo *TAI = MF->getTarget().getTargetAsmInfo();
407
408 // Basic size info comes from the TSFlags field.
409 const TargetInstrDesc &TID = MI->getDesc();
410 unsigned TSFlags = TID.TSFlags;
411
412 switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) {
413 default: {
414 // If this machine instr is an inline asm, measure it.
415 if (MI->getOpcode() == ARM::INLINEASM)
416 return TAI->getInlineAsmLength(MI->getOperand(0).getSymbolName());
417 if (MI->isLabel())
418 return 0;
419 switch (MI->getOpcode()) {
420 default:
Torok Edwinc23197a2009-07-14 16:55:14 +0000421 llvm_unreachable("Unknown or unset size field for instr!");
David Goodwin334c2642009-07-08 16:09:28 +0000422 case TargetInstrInfo::IMPLICIT_DEF:
423 case TargetInstrInfo::DECLARE:
424 case TargetInstrInfo::DBG_LABEL:
425 case TargetInstrInfo::EH_LABEL:
426 return 0;
427 }
428 break;
429 }
Evan Cheng78947622009-07-24 18:20:44 +0000430 case ARMII::Size8Bytes: return 8; // ARM instruction x 2.
431 case ARMII::Size4Bytes: return 4; // ARM / Thumb2 instruction.
432 case ARMII::Size2Bytes: return 2; // Thumb1 instruction.
David Goodwin334c2642009-07-08 16:09:28 +0000433 case ARMII::SizeSpecial: {
Evan Cheng78947622009-07-24 18:20:44 +0000434 bool IsThumb1JT = false;
David Goodwin334c2642009-07-08 16:09:28 +0000435 switch (MI->getOpcode()) {
436 case ARM::CONSTPOOL_ENTRY:
437 // If this machine instr is a constant pool entry, its size is recorded as
438 // operand #2.
439 return MI->getOperand(2).getImm();
Evan Cheng78947622009-07-24 18:20:44 +0000440 case ARM::Int_eh_sjlj_setjmp:
441 return 12;
442 case ARM::tBR_JTr:
443 IsThumb1JT = true;
444 // Fallthrough
David Goodwin334c2642009-07-08 16:09:28 +0000445 case ARM::BR_JTr:
446 case ARM::BR_JTm:
447 case ARM::BR_JTadd:
Evan Cheng66ac5312009-07-25 00:33:29 +0000448 case ARM::t2BR_JT: {
David Goodwin334c2642009-07-08 16:09:28 +0000449 // These are jumptable branches, i.e. a branch followed by an inlined
450 // jumptable. The size is 4 + 4 * number of entries.
451 unsigned NumOps = TID.getNumOperands();
452 MachineOperand JTOP =
453 MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2));
454 unsigned JTI = JTOP.getIndex();
455 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
456 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
457 assert(JTI < JT.size());
458 // Thumb instructions are 2 byte aligned, but JT entries are 4 byte
459 // 4 aligned. The assembler / linker may add 2 byte padding just before
460 // the JT entries. The size does not include this padding; the
461 // constant islands pass does separate bookkeeping for it.
462 // FIXME: If we know the size of the function is less than (1 << 16) *2
463 // bytes, we can use 16-bit entries instead. Then there won't be an
464 // alignment issue.
Evan Cheng78947622009-07-24 18:20:44 +0000465 return getNumJTEntries(JT, JTI) * 4 + (IsThumb1JT ? 2 : 4);
David Goodwin334c2642009-07-08 16:09:28 +0000466 }
467 default:
468 // Otherwise, pseudo-instruction sizes are zero.
469 return 0;
470 }
471 }
472 }
473 return 0; // Not reached
474}
475
476/// Return true if the instruction is a register to register move and
477/// leave the source and dest operands in the passed parameters.
478///
479bool
480ARMBaseInstrInfo::isMoveInstr(const MachineInstr &MI,
481 unsigned &SrcReg, unsigned &DstReg,
482 unsigned& SrcSubIdx, unsigned& DstSubIdx) const {
483 SrcSubIdx = DstSubIdx = 0; // No sub-registers.
484
Evan Cheng68e3c6a2009-07-27 00:05:15 +0000485 switch (MI.getOpcode()) {
Evan Chengdced03f2009-07-27 00:24:36 +0000486 default: break;
Evan Cheng68e3c6a2009-07-27 00:05:15 +0000487 case ARM::FCPYS:
488 case ARM::FCPYD:
489 case ARM::VMOVD:
490 case ARM::VMOVQ: {
David Goodwin334c2642009-07-08 16:09:28 +0000491 SrcReg = MI.getOperand(1).getReg();
492 DstReg = MI.getOperand(0).getReg();
493 return true;
494 }
Evan Cheng68e3c6a2009-07-27 00:05:15 +0000495 case ARM::MOVr:
496 case ARM::tMOVr:
497 case ARM::tMOVgpr2tgpr:
498 case ARM::tMOVtgpr2gpr:
499 case ARM::tMOVgpr2gpr:
500 case ARM::t2MOVr: {
David Goodwin334c2642009-07-08 16:09:28 +0000501 assert(MI.getDesc().getNumOperands() >= 2 &&
502 MI.getOperand(0).isReg() &&
503 MI.getOperand(1).isReg() &&
504 "Invalid ARM MOV instruction");
505 SrcReg = MI.getOperand(1).getReg();
506 DstReg = MI.getOperand(0).getReg();
507 return true;
508 }
Evan Cheng68e3c6a2009-07-27 00:05:15 +0000509 }
David Goodwin334c2642009-07-08 16:09:28 +0000510
511 return false;
512}
513
514unsigned
515ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
516 int &FrameIndex) const {
Evan Chengdced03f2009-07-27 00:24:36 +0000517 switch (MI->getOpcode()) {
518 default: break;
519 case ARM::LDR:
520 case ARM::t2LDRs: // FIXME: don't use t2LDRs to access frame.
David Goodwin334c2642009-07-08 16:09:28 +0000521 if (MI->getOperand(1).isFI() &&
522 MI->getOperand(2).isReg() &&
523 MI->getOperand(3).isImm() &&
524 MI->getOperand(2).getReg() == 0 &&
525 MI->getOperand(3).getImm() == 0) {
526 FrameIndex = MI->getOperand(1).getIndex();
527 return MI->getOperand(0).getReg();
528 }
Evan Chengdced03f2009-07-27 00:24:36 +0000529 break;
530 case ARM::t2LDRi12:
531 case ARM::tRestore:
David Goodwin5ff58b52009-07-24 00:16:18 +0000532 if (MI->getOperand(1).isFI() &&
533 MI->getOperand(2).isImm() &&
534 MI->getOperand(2).getImm() == 0) {
535 FrameIndex = MI->getOperand(1).getIndex();
536 return MI->getOperand(0).getReg();
537 }
Evan Chengdced03f2009-07-27 00:24:36 +0000538 break;
539 case ARM::FLDD:
540 case ARM::FLDS:
David Goodwin334c2642009-07-08 16:09:28 +0000541 if (MI->getOperand(1).isFI() &&
542 MI->getOperand(2).isImm() &&
543 MI->getOperand(2).getImm() == 0) {
544 FrameIndex = MI->getOperand(1).getIndex();
545 return MI->getOperand(0).getReg();
546 }
Evan Chengdced03f2009-07-27 00:24:36 +0000547 break;
David Goodwin334c2642009-07-08 16:09:28 +0000548 }
549
550 return 0;
551}
552
553unsigned
554ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
555 int &FrameIndex) const {
Evan Chengdced03f2009-07-27 00:24:36 +0000556 switch (MI->getOpcode()) {
557 default: break;
558 case ARM::STR:
559 case ARM::t2STRs: // FIXME: don't use t2STRs to access frame.
David Goodwin334c2642009-07-08 16:09:28 +0000560 if (MI->getOperand(1).isFI() &&
561 MI->getOperand(2).isReg() &&
562 MI->getOperand(3).isImm() &&
563 MI->getOperand(2).getReg() == 0 &&
564 MI->getOperand(3).getImm() == 0) {
565 FrameIndex = MI->getOperand(1).getIndex();
566 return MI->getOperand(0).getReg();
567 }
Evan Chengdced03f2009-07-27 00:24:36 +0000568 break;
569 case ARM::t2STRi12:
570 case ARM::tSpill:
David Goodwin5ff58b52009-07-24 00:16:18 +0000571 if (MI->getOperand(1).isFI() &&
572 MI->getOperand(2).isImm() &&
573 MI->getOperand(2).getImm() == 0) {
574 FrameIndex = MI->getOperand(1).getIndex();
575 return MI->getOperand(0).getReg();
576 }
Evan Chengdced03f2009-07-27 00:24:36 +0000577 break;
578 case ARM::FSTD:
579 case ARM::FSTS:
David Goodwin334c2642009-07-08 16:09:28 +0000580 if (MI->getOperand(1).isFI() &&
581 MI->getOperand(2).isImm() &&
582 MI->getOperand(2).getImm() == 0) {
583 FrameIndex = MI->getOperand(1).getIndex();
584 return MI->getOperand(0).getReg();
585 }
Evan Chengdced03f2009-07-27 00:24:36 +0000586 break;
David Goodwin334c2642009-07-08 16:09:28 +0000587 }
588
589 return 0;
590}
591
592bool
593ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
594 MachineBasicBlock::iterator I,
595 unsigned DestReg, unsigned SrcReg,
596 const TargetRegisterClass *DestRC,
597 const TargetRegisterClass *SrcRC) const {
598 DebugLoc DL = DebugLoc::getUnknownLoc();
599 if (I != MBB.end()) DL = I->getDebugLoc();
600
601 if (DestRC != SrcRC) {
602 // Not yet supported!
603 return false;
604 }
605
606 if (DestRC == ARM::GPRRegisterClass)
Evan Cheng08b93c62009-07-27 00:33:08 +0000607 AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr),
Evan Chengdd6f6322009-07-11 06:37:27 +0000608 DestReg).addReg(SrcReg)));
David Goodwin334c2642009-07-08 16:09:28 +0000609 else if (DestRC == ARM::SPRRegisterClass)
Evan Chengb74bb1a2009-07-24 00:53:56 +0000610 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FCPYS), DestReg)
David Goodwin334c2642009-07-08 16:09:28 +0000611 .addReg(SrcReg));
612 else if (DestRC == ARM::DPRRegisterClass)
Evan Chengb74bb1a2009-07-24 00:53:56 +0000613 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FCPYD), DestReg)
David Goodwin334c2642009-07-08 16:09:28 +0000614 .addReg(SrcReg));
615 else if (DestRC == ARM::QPRRegisterClass)
Evan Chengb74bb1a2009-07-24 00:53:56 +0000616 BuildMI(MBB, I, DL, get(ARM::VMOVQ), DestReg).addReg(SrcReg);
David Goodwin334c2642009-07-08 16:09:28 +0000617 else
618 return false;
619
620 return true;
621}
622
623void ARMBaseInstrInfo::
624storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
625 unsigned SrcReg, bool isKill, int FI,
626 const TargetRegisterClass *RC) const {
627 DebugLoc DL = DebugLoc::getUnknownLoc();
628 if (I != MBB.end()) DL = I->getDebugLoc();
629
630 if (RC == ARM::GPRRegisterClass) {
Evan Cheng5732ca02009-07-27 03:14:20 +0000631 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STR))
David Goodwin334c2642009-07-08 16:09:28 +0000632 .addReg(SrcReg, getKillRegState(isKill))
633 .addFrameIndex(FI).addReg(0).addImm(0));
634 } else if (RC == ARM::DPRRegisterClass) {
Evan Chengb74bb1a2009-07-24 00:53:56 +0000635 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FSTD))
David Goodwin334c2642009-07-08 16:09:28 +0000636 .addReg(SrcReg, getKillRegState(isKill))
637 .addFrameIndex(FI).addImm(0));
638 } else {
639 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
Evan Chengb74bb1a2009-07-24 00:53:56 +0000640 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FSTS))
David Goodwin334c2642009-07-08 16:09:28 +0000641 .addReg(SrcReg, getKillRegState(isKill))
642 .addFrameIndex(FI).addImm(0));
643 }
644}
645
David Goodwin334c2642009-07-08 16:09:28 +0000646void ARMBaseInstrInfo::
647loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
648 unsigned DestReg, int FI,
649 const TargetRegisterClass *RC) const {
650 DebugLoc DL = DebugLoc::getUnknownLoc();
651 if (I != MBB.end()) DL = I->getDebugLoc();
652
653 if (RC == ARM::GPRRegisterClass) {
Evan Cheng5732ca02009-07-27 03:14:20 +0000654 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDR), DestReg)
David Goodwin334c2642009-07-08 16:09:28 +0000655 .addFrameIndex(FI).addReg(0).addImm(0));
656 } else if (RC == ARM::DPRRegisterClass) {
Evan Chengb74bb1a2009-07-24 00:53:56 +0000657 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FLDD), DestReg)
David Goodwin334c2642009-07-08 16:09:28 +0000658 .addFrameIndex(FI).addImm(0));
659 } else {
660 assert(RC == ARM::SPRRegisterClass && "Unknown regclass!");
Evan Chengb74bb1a2009-07-24 00:53:56 +0000661 AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::FLDS), DestReg)
David Goodwin334c2642009-07-08 16:09:28 +0000662 .addFrameIndex(FI).addImm(0));
663 }
664}
665
David Goodwin334c2642009-07-08 16:09:28 +0000666MachineInstr *ARMBaseInstrInfo::
667foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
668 const SmallVectorImpl<unsigned> &Ops, int FI) const {
669 if (Ops.size() != 1) return NULL;
670
671 unsigned OpNum = Ops[0];
672 unsigned Opc = MI->getOpcode();
673 MachineInstr *NewMI = NULL;
Evan Cheng5732ca02009-07-27 03:14:20 +0000674 if (Opc == ARM::MOVr || Opc == ARM::t2MOVr) {
David Goodwin334c2642009-07-08 16:09:28 +0000675 // If it is updating CPSR, then it cannot be folded.
Evan Cheng1f5c9882009-07-27 04:18:04 +0000676 if (MI->getOperand(4).getReg() != ARM::CPSR || MI->getOperand(4).isDead()) {
David Goodwin334c2642009-07-08 16:09:28 +0000677 unsigned Pred = MI->getOperand(2).getImm();
678 unsigned PredReg = MI->getOperand(3).getReg();
679 if (OpNum == 0) { // move -> store
680 unsigned SrcReg = MI->getOperand(1).getReg();
681 bool isKill = MI->getOperand(1).isKill();
682 bool isUndef = MI->getOperand(1).isUndef();
Evan Cheng5732ca02009-07-27 03:14:20 +0000683 if (Opc == ARM::MOVr)
684 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::STR))
685 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef))
686 .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
687 else // ARM::t2MOVr
688 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2STRi12))
689 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef))
690 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
David Goodwin334c2642009-07-08 16:09:28 +0000691 } else { // move -> load
692 unsigned DstReg = MI->getOperand(0).getReg();
693 bool isDead = MI->getOperand(0).isDead();
694 bool isUndef = MI->getOperand(0).isUndef();
Evan Cheng5732ca02009-07-27 03:14:20 +0000695 if (Opc == ARM::MOVr)
696 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::LDR))
697 .addReg(DstReg,
698 RegState::Define |
699 getDeadRegState(isDead) |
700 getUndefRegState(isUndef))
701 .addFrameIndex(FI).addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
702 else // ARM::t2MOVr
703 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::t2LDRi12))
704 .addReg(DstReg,
705 RegState::Define |
706 getDeadRegState(isDead) |
707 getUndefRegState(isUndef))
708 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
David Goodwin334c2642009-07-08 16:09:28 +0000709 }
710 }
711 }
Evan Chengb74bb1a2009-07-24 00:53:56 +0000712 else if (Opc == ARM::FCPYS) {
David Goodwin334c2642009-07-08 16:09:28 +0000713 unsigned Pred = MI->getOperand(2).getImm();
714 unsigned PredReg = MI->getOperand(3).getReg();
715 if (OpNum == 0) { // move -> store
716 unsigned SrcReg = MI->getOperand(1).getReg();
717 bool isKill = MI->getOperand(1).isKill();
718 bool isUndef = MI->getOperand(1).isUndef();
Evan Chengb74bb1a2009-07-24 00:53:56 +0000719 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::FSTS))
David Goodwin334c2642009-07-08 16:09:28 +0000720 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef))
721 .addFrameIndex(FI)
722 .addImm(0).addImm(Pred).addReg(PredReg);
723 } else { // move -> load
724 unsigned DstReg = MI->getOperand(0).getReg();
725 bool isDead = MI->getOperand(0).isDead();
726 bool isUndef = MI->getOperand(0).isUndef();
Evan Chengb74bb1a2009-07-24 00:53:56 +0000727 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::FLDS))
David Goodwin334c2642009-07-08 16:09:28 +0000728 .addReg(DstReg,
729 RegState::Define |
730 getDeadRegState(isDead) |
731 getUndefRegState(isUndef))
732 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
733 }
734 }
Evan Chengb74bb1a2009-07-24 00:53:56 +0000735 else if (Opc == ARM::FCPYD) {
David Goodwin334c2642009-07-08 16:09:28 +0000736 unsigned Pred = MI->getOperand(2).getImm();
737 unsigned PredReg = MI->getOperand(3).getReg();
738 if (OpNum == 0) { // move -> store
739 unsigned SrcReg = MI->getOperand(1).getReg();
740 bool isKill = MI->getOperand(1).isKill();
741 bool isUndef = MI->getOperand(1).isUndef();
Evan Chengb74bb1a2009-07-24 00:53:56 +0000742 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::FSTD))
David Goodwin334c2642009-07-08 16:09:28 +0000743 .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef))
744 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
745 } else { // move -> load
746 unsigned DstReg = MI->getOperand(0).getReg();
747 bool isDead = MI->getOperand(0).isDead();
748 bool isUndef = MI->getOperand(0).isUndef();
Evan Chengb74bb1a2009-07-24 00:53:56 +0000749 NewMI = BuildMI(MF, MI->getDebugLoc(), get(ARM::FLDD))
David Goodwin334c2642009-07-08 16:09:28 +0000750 .addReg(DstReg,
751 RegState::Define |
752 getDeadRegState(isDead) |
753 getUndefRegState(isUndef))
754 .addFrameIndex(FI).addImm(0).addImm(Pred).addReg(PredReg);
755 }
756 }
757
758 return NewMI;
759}
760
761MachineInstr*
762ARMBaseInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
763 MachineInstr* MI,
764 const SmallVectorImpl<unsigned> &Ops,
765 MachineInstr* LoadMI) const {
Evan Cheng1f5c9882009-07-27 04:18:04 +0000766 // FIXME
David Goodwin334c2642009-07-08 16:09:28 +0000767 return 0;
768}
769
770bool
771ARMBaseInstrInfo::canFoldMemoryOperand(const MachineInstr *MI,
772 const SmallVectorImpl<unsigned> &Ops) const {
773 if (Ops.size() != 1) return false;
774
775 unsigned Opc = MI->getOpcode();
Evan Cheng5732ca02009-07-27 03:14:20 +0000776 if (Opc == ARM::MOVr || Opc == ARM::t2MOVr) {
David Goodwin334c2642009-07-08 16:09:28 +0000777 // If it is updating CPSR, then it cannot be folded.
Evan Cheng1f5c9882009-07-27 04:18:04 +0000778 return MI->getOperand(4).getReg() != ARM::CPSR ||MI->getOperand(4).isDead();
Evan Chengb74bb1a2009-07-24 00:53:56 +0000779 } else if (Opc == ARM::FCPYS || Opc == ARM::FCPYD) {
David Goodwin334c2642009-07-08 16:09:28 +0000780 return true;
Evan Chengb74bb1a2009-07-24 00:53:56 +0000781 } else if (Opc == ARM::VMOVD || Opc == ARM::VMOVQ) {
David Goodwin334c2642009-07-08 16:09:28 +0000782 return false; // FIXME
783 }
784
785 return false;
786}
Evan Cheng5ca53a72009-07-27 18:20:05 +0000787
788int ARMBaseInstrInfo::getMatchingCondBranchOpcode(int Opc) const {
789 if (Opc == ARM::B)
790 return ARM::Bcc;
791 else if (Opc == ARM::tB)
792 return ARM::tBcc;
793 else if (Opc == ARM::t2B)
794 return ARM::t2Bcc;
795
796 llvm_unreachable("Unknown unconditional branch opcode!");
797 return 0;
798}
799