1*9880d681SAndroid Build Coastguard Worker //===-- AVRInstrInfo.cpp - AVR Instruction Information --------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains the AVR implementation of the TargetInstrInfo class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "AVRInstrInfo.h"
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineConstantPool.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineMemOperand.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker #include "AVR.h"
29*9880d681SAndroid Build Coastguard Worker #include "AVRMachineFunctionInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "AVRTargetMachine.h"
31*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AVRMCTargetDesc.h"
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker #define GET_INSTRINFO_CTOR_DTOR
34*9880d681SAndroid Build Coastguard Worker #include "AVRGenInstrInfo.inc"
35*9880d681SAndroid Build Coastguard Worker
36*9880d681SAndroid Build Coastguard Worker namespace llvm {
37*9880d681SAndroid Build Coastguard Worker
AVRInstrInfo()38*9880d681SAndroid Build Coastguard Worker AVRInstrInfo::AVRInstrInfo()
39*9880d681SAndroid Build Coastguard Worker : AVRGenInstrInfo(AVR::ADJCALLSTACKDOWN, AVR::ADJCALLSTACKUP), RI() {}
40*9880d681SAndroid Build Coastguard Worker
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const DebugLoc & DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const41*9880d681SAndroid Build Coastguard Worker void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
42*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MI,
43*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL, unsigned DestReg,
44*9880d681SAndroid Build Coastguard Worker unsigned SrcReg, bool KillSrc) const {
45*9880d681SAndroid Build Coastguard Worker unsigned Opc;
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {
48*9880d681SAndroid Build Coastguard Worker Opc = AVR::MOVRdRr;
49*9880d681SAndroid Build Coastguard Worker } else if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {
50*9880d681SAndroid Build Coastguard Worker Opc = AVR::MOVWRdRr;
51*9880d681SAndroid Build Coastguard Worker } else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {
52*9880d681SAndroid Build Coastguard Worker Opc = AVR::SPREAD;
53*9880d681SAndroid Build Coastguard Worker } else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {
54*9880d681SAndroid Build Coastguard Worker Opc = AVR::SPWRITE;
55*9880d681SAndroid Build Coastguard Worker } else {
56*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Impossible reg-to-reg copy");
57*9880d681SAndroid Build Coastguard Worker }
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(Opc), DestReg)
60*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(KillSrc));
61*9880d681SAndroid Build Coastguard Worker }
62*9880d681SAndroid Build Coastguard Worker
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const63*9880d681SAndroid Build Coastguard Worker unsigned AVRInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
64*9880d681SAndroid Build Coastguard Worker int &FrameIndex) const {
65*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
66*9880d681SAndroid Build Coastguard Worker case AVR::LDDRdPtrQ:
67*9880d681SAndroid Build Coastguard Worker case AVR::LDDWRdYQ: { //:FIXME: remove this once PR13375 gets fixed
68*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
69*9880d681SAndroid Build Coastguard Worker MI.getOperand(2).getImm() == 0) {
70*9880d681SAndroid Build Coastguard Worker FrameIndex = MI.getOperand(1).getIndex();
71*9880d681SAndroid Build Coastguard Worker return MI.getOperand(0).getReg();
72*9880d681SAndroid Build Coastguard Worker }
73*9880d681SAndroid Build Coastguard Worker break;
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker default:
76*9880d681SAndroid Build Coastguard Worker break;
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Worker return 0;
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const82*9880d681SAndroid Build Coastguard Worker unsigned AVRInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
83*9880d681SAndroid Build Coastguard Worker int &FrameIndex) const {
84*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
85*9880d681SAndroid Build Coastguard Worker case AVR::STDPtrQRr:
86*9880d681SAndroid Build Coastguard Worker case AVR::STDWPtrQRr: {
87*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
88*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).getImm() == 0) {
89*9880d681SAndroid Build Coastguard Worker FrameIndex = MI.getOperand(0).getIndex();
90*9880d681SAndroid Build Coastguard Worker return MI.getOperand(2).getReg();
91*9880d681SAndroid Build Coastguard Worker }
92*9880d681SAndroid Build Coastguard Worker break;
93*9880d681SAndroid Build Coastguard Worker }
94*9880d681SAndroid Build Coastguard Worker default:
95*9880d681SAndroid Build Coastguard Worker break;
96*9880d681SAndroid Build Coastguard Worker }
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker return 0;
99*9880d681SAndroid Build Coastguard Worker }
100*9880d681SAndroid Build Coastguard Worker
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,unsigned SrcReg,bool isKill,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const101*9880d681SAndroid Build Coastguard Worker void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
102*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MI,
103*9880d681SAndroid Build Coastguard Worker unsigned SrcReg, bool isKill,
104*9880d681SAndroid Build Coastguard Worker int FrameIndex,
105*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC,
106*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) const {
107*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = *MBB.getParent();
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker DebugLoc DL;
110*9880d681SAndroid Build Coastguard Worker if (MI != MBB.end()) {
111*9880d681SAndroid Build Coastguard Worker DL = MI->getDebugLoc();
112*9880d681SAndroid Build Coastguard Worker }
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker const MachineFrameInfo &MFI = *MF.getFrameInfo();
115*9880d681SAndroid Build Coastguard Worker
116*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO = MF.getMachineMemOperand(
117*9880d681SAndroid Build Coastguard Worker MachinePointerInfo::getFixedStack(MF, FrameIndex),
118*9880d681SAndroid Build Coastguard Worker MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
119*9880d681SAndroid Build Coastguard Worker MFI.getObjectAlignment(FrameIndex));
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker unsigned Opcode = 0;
122*9880d681SAndroid Build Coastguard Worker if (RC->hasType(MVT::i8)) {
123*9880d681SAndroid Build Coastguard Worker Opcode = AVR::STDPtrQRr;
124*9880d681SAndroid Build Coastguard Worker } else if (RC->hasType(MVT::i16)) {
125*9880d681SAndroid Build Coastguard Worker Opcode = AVR::STDWPtrQRr;
126*9880d681SAndroid Build Coastguard Worker } else {
127*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Cannot store this register into a stack slot!");
128*9880d681SAndroid Build Coastguard Worker }
129*9880d681SAndroid Build Coastguard Worker
130*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(Opcode))
131*9880d681SAndroid Build Coastguard Worker .addFrameIndex(FrameIndex)
132*9880d681SAndroid Build Coastguard Worker .addImm(0)
133*9880d681SAndroid Build Coastguard Worker .addReg(SrcReg, getKillRegState(isKill))
134*9880d681SAndroid Build Coastguard Worker .addMemOperand(MMO);
135*9880d681SAndroid Build Coastguard Worker }
136*9880d681SAndroid Build Coastguard Worker
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,unsigned DestReg,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const137*9880d681SAndroid Build Coastguard Worker void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
138*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MI,
139*9880d681SAndroid Build Coastguard Worker unsigned DestReg, int FrameIndex,
140*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC,
141*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) const {
142*9880d681SAndroid Build Coastguard Worker DebugLoc DL;
143*9880d681SAndroid Build Coastguard Worker if (MI != MBB.end()) {
144*9880d681SAndroid Build Coastguard Worker DL = MI->getDebugLoc();
145*9880d681SAndroid Build Coastguard Worker }
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = *MBB.getParent();
148*9880d681SAndroid Build Coastguard Worker const MachineFrameInfo &MFI = *MF.getFrameInfo();
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO = MF.getMachineMemOperand(
151*9880d681SAndroid Build Coastguard Worker MachinePointerInfo::getFixedStack(MF, FrameIndex),
152*9880d681SAndroid Build Coastguard Worker MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
153*9880d681SAndroid Build Coastguard Worker MFI.getObjectAlignment(FrameIndex));
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker unsigned Opcode = 0;
156*9880d681SAndroid Build Coastguard Worker if (RC->hasType(MVT::i8)) {
157*9880d681SAndroid Build Coastguard Worker Opcode = AVR::LDDRdPtrQ;
158*9880d681SAndroid Build Coastguard Worker } else if (RC->hasType(MVT::i16)) {
159*9880d681SAndroid Build Coastguard Worker // Opcode = AVR::LDDWRdPtrQ;
160*9880d681SAndroid Build Coastguard Worker //:FIXME: remove this once PR13375 gets fixed
161*9880d681SAndroid Build Coastguard Worker Opcode = AVR::LDDWRdYQ;
162*9880d681SAndroid Build Coastguard Worker } else {
163*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Cannot load this register from a stack slot!");
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, get(Opcode), DestReg)
167*9880d681SAndroid Build Coastguard Worker .addFrameIndex(FrameIndex)
168*9880d681SAndroid Build Coastguard Worker .addImm(0)
169*9880d681SAndroid Build Coastguard Worker .addMemOperand(MMO);
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
getBrCond(AVRCC::CondCodes CC) const172*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {
173*9880d681SAndroid Build Coastguard Worker switch (CC) {
174*9880d681SAndroid Build Coastguard Worker default:
175*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown condition code!");
176*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_EQ:
177*9880d681SAndroid Build Coastguard Worker return get(AVR::BREQk);
178*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_NE:
179*9880d681SAndroid Build Coastguard Worker return get(AVR::BRNEk);
180*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_GE:
181*9880d681SAndroid Build Coastguard Worker return get(AVR::BRGEk);
182*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_LT:
183*9880d681SAndroid Build Coastguard Worker return get(AVR::BRLTk);
184*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_SH:
185*9880d681SAndroid Build Coastguard Worker return get(AVR::BRSHk);
186*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_LO:
187*9880d681SAndroid Build Coastguard Worker return get(AVR::BRLOk);
188*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_MI:
189*9880d681SAndroid Build Coastguard Worker return get(AVR::BRMIk);
190*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_PL:
191*9880d681SAndroid Build Coastguard Worker return get(AVR::BRPLk);
192*9880d681SAndroid Build Coastguard Worker }
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker
getCondFromBranchOpc(unsigned Opc) const195*9880d681SAndroid Build Coastguard Worker AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {
196*9880d681SAndroid Build Coastguard Worker switch (Opc) {
197*9880d681SAndroid Build Coastguard Worker default:
198*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_INVALID;
199*9880d681SAndroid Build Coastguard Worker case AVR::BREQk:
200*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_EQ;
201*9880d681SAndroid Build Coastguard Worker case AVR::BRNEk:
202*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_NE;
203*9880d681SAndroid Build Coastguard Worker case AVR::BRSHk:
204*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_SH;
205*9880d681SAndroid Build Coastguard Worker case AVR::BRLOk:
206*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_LO;
207*9880d681SAndroid Build Coastguard Worker case AVR::BRMIk:
208*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_MI;
209*9880d681SAndroid Build Coastguard Worker case AVR::BRPLk:
210*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_PL;
211*9880d681SAndroid Build Coastguard Worker case AVR::BRGEk:
212*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_GE;
213*9880d681SAndroid Build Coastguard Worker case AVR::BRLTk:
214*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_LT;
215*9880d681SAndroid Build Coastguard Worker }
216*9880d681SAndroid Build Coastguard Worker }
217*9880d681SAndroid Build Coastguard Worker
getOppositeCondition(AVRCC::CondCodes CC) const218*9880d681SAndroid Build Coastguard Worker AVRCC::CondCodes AVRInstrInfo::getOppositeCondition(AVRCC::CondCodes CC) const {
219*9880d681SAndroid Build Coastguard Worker switch (CC) {
220*9880d681SAndroid Build Coastguard Worker default:
221*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid condition!");
222*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_EQ:
223*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_NE;
224*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_NE:
225*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_EQ;
226*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_SH:
227*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_LO;
228*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_LO:
229*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_SH;
230*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_GE:
231*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_LT;
232*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_LT:
233*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_GE;
234*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_MI:
235*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_PL;
236*9880d681SAndroid Build Coastguard Worker case AVRCC::COND_PL:
237*9880d681SAndroid Build Coastguard Worker return AVRCC::COND_MI;
238*9880d681SAndroid Build Coastguard Worker }
239*9880d681SAndroid Build Coastguard Worker }
240*9880d681SAndroid Build Coastguard Worker
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const241*9880d681SAndroid Build Coastguard Worker bool AVRInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
242*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *&TBB,
243*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *&FBB,
244*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineOperand> &Cond,
245*9880d681SAndroid Build Coastguard Worker bool AllowModify) const {
246*9880d681SAndroid Build Coastguard Worker // Start from the bottom of the block and work up, examining the
247*9880d681SAndroid Build Coastguard Worker // terminator instructions.
248*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I = MBB.end();
249*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator UnCondBrIter = MBB.end();
250*9880d681SAndroid Build Coastguard Worker
251*9880d681SAndroid Build Coastguard Worker while (I != MBB.begin()) {
252*9880d681SAndroid Build Coastguard Worker --I;
253*9880d681SAndroid Build Coastguard Worker if (I->isDebugValue()) {
254*9880d681SAndroid Build Coastguard Worker continue;
255*9880d681SAndroid Build Coastguard Worker }
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard Worker // Working from the bottom, when we see a non-terminator
258*9880d681SAndroid Build Coastguard Worker // instruction, we're done.
259*9880d681SAndroid Build Coastguard Worker if (!isUnpredicatedTerminator(*I)) {
260*9880d681SAndroid Build Coastguard Worker break;
261*9880d681SAndroid Build Coastguard Worker }
262*9880d681SAndroid Build Coastguard Worker
263*9880d681SAndroid Build Coastguard Worker // A terminator that isn't a branch can't easily be handled
264*9880d681SAndroid Build Coastguard Worker // by this analysis.
265*9880d681SAndroid Build Coastguard Worker if (!I->getDesc().isBranch()) {
266*9880d681SAndroid Build Coastguard Worker return true;
267*9880d681SAndroid Build Coastguard Worker }
268*9880d681SAndroid Build Coastguard Worker
269*9880d681SAndroid Build Coastguard Worker // Handle unconditional branches.
270*9880d681SAndroid Build Coastguard Worker //:TODO: add here jmp
271*9880d681SAndroid Build Coastguard Worker if (I->getOpcode() == AVR::RJMPk) {
272*9880d681SAndroid Build Coastguard Worker UnCondBrIter = I;
273*9880d681SAndroid Build Coastguard Worker
274*9880d681SAndroid Build Coastguard Worker if (!AllowModify) {
275*9880d681SAndroid Build Coastguard Worker TBB = I->getOperand(0).getMBB();
276*9880d681SAndroid Build Coastguard Worker continue;
277*9880d681SAndroid Build Coastguard Worker }
278*9880d681SAndroid Build Coastguard Worker
279*9880d681SAndroid Build Coastguard Worker // If the block has any instructions after a JMP, delete them.
280*9880d681SAndroid Build Coastguard Worker while (std::next(I) != MBB.end()) {
281*9880d681SAndroid Build Coastguard Worker std::next(I)->eraseFromParent();
282*9880d681SAndroid Build Coastguard Worker }
283*9880d681SAndroid Build Coastguard Worker
284*9880d681SAndroid Build Coastguard Worker Cond.clear();
285*9880d681SAndroid Build Coastguard Worker FBB = 0;
286*9880d681SAndroid Build Coastguard Worker
287*9880d681SAndroid Build Coastguard Worker // Delete the JMP if it's equivalent to a fall-through.
288*9880d681SAndroid Build Coastguard Worker if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
289*9880d681SAndroid Build Coastguard Worker TBB = 0;
290*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
291*9880d681SAndroid Build Coastguard Worker I = MBB.end();
292*9880d681SAndroid Build Coastguard Worker UnCondBrIter = MBB.end();
293*9880d681SAndroid Build Coastguard Worker continue;
294*9880d681SAndroid Build Coastguard Worker }
295*9880d681SAndroid Build Coastguard Worker
296*9880d681SAndroid Build Coastguard Worker // TBB is used to indicate the unconditinal destination.
297*9880d681SAndroid Build Coastguard Worker TBB = I->getOperand(0).getMBB();
298*9880d681SAndroid Build Coastguard Worker continue;
299*9880d681SAndroid Build Coastguard Worker }
300*9880d681SAndroid Build Coastguard Worker
301*9880d681SAndroid Build Coastguard Worker // Handle conditional branches.
302*9880d681SAndroid Build Coastguard Worker AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());
303*9880d681SAndroid Build Coastguard Worker if (BranchCode == AVRCC::COND_INVALID) {
304*9880d681SAndroid Build Coastguard Worker return true; // Can't handle indirect branch.
305*9880d681SAndroid Build Coastguard Worker }
306*9880d681SAndroid Build Coastguard Worker
307*9880d681SAndroid Build Coastguard Worker // Working from the bottom, handle the first conditional branch.
308*9880d681SAndroid Build Coastguard Worker if (Cond.empty()) {
309*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
310*9880d681SAndroid Build Coastguard Worker if (AllowModify && UnCondBrIter != MBB.end() &&
311*9880d681SAndroid Build Coastguard Worker MBB.isLayoutSuccessor(TargetBB)) {
312*9880d681SAndroid Build Coastguard Worker // If we can modify the code and it ends in something like:
313*9880d681SAndroid Build Coastguard Worker //
314*9880d681SAndroid Build Coastguard Worker // jCC L1
315*9880d681SAndroid Build Coastguard Worker // jmp L2
316*9880d681SAndroid Build Coastguard Worker // L1:
317*9880d681SAndroid Build Coastguard Worker // ...
318*9880d681SAndroid Build Coastguard Worker // L2:
319*9880d681SAndroid Build Coastguard Worker //
320*9880d681SAndroid Build Coastguard Worker // Then we can change this to:
321*9880d681SAndroid Build Coastguard Worker //
322*9880d681SAndroid Build Coastguard Worker // jnCC L2
323*9880d681SAndroid Build Coastguard Worker // L1:
324*9880d681SAndroid Build Coastguard Worker // ...
325*9880d681SAndroid Build Coastguard Worker // L2:
326*9880d681SAndroid Build Coastguard Worker //
327*9880d681SAndroid Build Coastguard Worker // Which is a bit more efficient.
328*9880d681SAndroid Build Coastguard Worker // We conditionally jump to the fall-through block.
329*9880d681SAndroid Build Coastguard Worker BranchCode = getOppositeCondition(BranchCode);
330*9880d681SAndroid Build Coastguard Worker unsigned JNCC = getBrCond(BranchCode).getOpcode();
331*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator OldInst = I;
332*9880d681SAndroid Build Coastguard Worker
333*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
334*9880d681SAndroid Build Coastguard Worker .addMBB(UnCondBrIter->getOperand(0).getMBB());
335*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk))
336*9880d681SAndroid Build Coastguard Worker .addMBB(TargetBB);
337*9880d681SAndroid Build Coastguard Worker
338*9880d681SAndroid Build Coastguard Worker OldInst->eraseFromParent();
339*9880d681SAndroid Build Coastguard Worker UnCondBrIter->eraseFromParent();
340*9880d681SAndroid Build Coastguard Worker
341*9880d681SAndroid Build Coastguard Worker // Restart the analysis.
342*9880d681SAndroid Build Coastguard Worker UnCondBrIter = MBB.end();
343*9880d681SAndroid Build Coastguard Worker I = MBB.end();
344*9880d681SAndroid Build Coastguard Worker continue;
345*9880d681SAndroid Build Coastguard Worker }
346*9880d681SAndroid Build Coastguard Worker
347*9880d681SAndroid Build Coastguard Worker FBB = TBB;
348*9880d681SAndroid Build Coastguard Worker TBB = I->getOperand(0).getMBB();
349*9880d681SAndroid Build Coastguard Worker Cond.push_back(MachineOperand::CreateImm(BranchCode));
350*9880d681SAndroid Build Coastguard Worker continue;
351*9880d681SAndroid Build Coastguard Worker }
352*9880d681SAndroid Build Coastguard Worker
353*9880d681SAndroid Build Coastguard Worker // Handle subsequent conditional branches. Only handle the case where all
354*9880d681SAndroid Build Coastguard Worker // conditional branches branch to the same destination.
355*9880d681SAndroid Build Coastguard Worker assert(Cond.size() == 1);
356*9880d681SAndroid Build Coastguard Worker assert(TBB);
357*9880d681SAndroid Build Coastguard Worker
358*9880d681SAndroid Build Coastguard Worker // Only handle the case where all conditional branches branch to
359*9880d681SAndroid Build Coastguard Worker // the same destination.
360*9880d681SAndroid Build Coastguard Worker if (TBB != I->getOperand(0).getMBB()) {
361*9880d681SAndroid Build Coastguard Worker return true;
362*9880d681SAndroid Build Coastguard Worker }
363*9880d681SAndroid Build Coastguard Worker
364*9880d681SAndroid Build Coastguard Worker AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm();
365*9880d681SAndroid Build Coastguard Worker // If the conditions are the same, we can leave them alone.
366*9880d681SAndroid Build Coastguard Worker if (OldBranchCode == BranchCode) {
367*9880d681SAndroid Build Coastguard Worker continue;
368*9880d681SAndroid Build Coastguard Worker }
369*9880d681SAndroid Build Coastguard Worker
370*9880d681SAndroid Build Coastguard Worker return true;
371*9880d681SAndroid Build Coastguard Worker }
372*9880d681SAndroid Build Coastguard Worker
373*9880d681SAndroid Build Coastguard Worker return false;
374*9880d681SAndroid Build Coastguard Worker }
375*9880d681SAndroid Build Coastguard Worker
InsertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL) const376*9880d681SAndroid Build Coastguard Worker unsigned AVRInstrInfo::InsertBranch(MachineBasicBlock &MBB,
377*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TBB,
378*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *FBB,
379*9880d681SAndroid Build Coastguard Worker ArrayRef<MachineOperand> Cond,
380*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL) const {
381*9880d681SAndroid Build Coastguard Worker // Shouldn't be a fall through.
382*9880d681SAndroid Build Coastguard Worker assert(TBB && "InsertBranch must not be told to insert a fallthrough");
383*9880d681SAndroid Build Coastguard Worker assert((Cond.size() == 1 || Cond.size() == 0) &&
384*9880d681SAndroid Build Coastguard Worker "AVR branch conditions have one component!");
385*9880d681SAndroid Build Coastguard Worker
386*9880d681SAndroid Build Coastguard Worker if (Cond.empty()) {
387*9880d681SAndroid Build Coastguard Worker assert(!FBB && "Unconditional branch with multiple successors!");
388*9880d681SAndroid Build Coastguard Worker BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);
389*9880d681SAndroid Build Coastguard Worker return 1;
390*9880d681SAndroid Build Coastguard Worker }
391*9880d681SAndroid Build Coastguard Worker
392*9880d681SAndroid Build Coastguard Worker // Conditional branch.
393*9880d681SAndroid Build Coastguard Worker unsigned Count = 0;
394*9880d681SAndroid Build Coastguard Worker AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();
395*9880d681SAndroid Build Coastguard Worker BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
396*9880d681SAndroid Build Coastguard Worker ++Count;
397*9880d681SAndroid Build Coastguard Worker
398*9880d681SAndroid Build Coastguard Worker if (FBB) {
399*9880d681SAndroid Build Coastguard Worker // Two-way Conditional branch. Insert the second branch.
400*9880d681SAndroid Build Coastguard Worker BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);
401*9880d681SAndroid Build Coastguard Worker ++Count;
402*9880d681SAndroid Build Coastguard Worker }
403*9880d681SAndroid Build Coastguard Worker
404*9880d681SAndroid Build Coastguard Worker return Count;
405*9880d681SAndroid Build Coastguard Worker }
406*9880d681SAndroid Build Coastguard Worker
RemoveBranch(MachineBasicBlock & MBB) const407*9880d681SAndroid Build Coastguard Worker unsigned AVRInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
408*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I = MBB.end();
409*9880d681SAndroid Build Coastguard Worker unsigned Count = 0;
410*9880d681SAndroid Build Coastguard Worker
411*9880d681SAndroid Build Coastguard Worker while (I != MBB.begin()) {
412*9880d681SAndroid Build Coastguard Worker --I;
413*9880d681SAndroid Build Coastguard Worker if (I->isDebugValue()) {
414*9880d681SAndroid Build Coastguard Worker continue;
415*9880d681SAndroid Build Coastguard Worker }
416*9880d681SAndroid Build Coastguard Worker //:TODO: add here the missing jmp instructions once they are implemented
417*9880d681SAndroid Build Coastguard Worker // like jmp, {e}ijmp, and other cond branches, ...
418*9880d681SAndroid Build Coastguard Worker if (I->getOpcode() != AVR::RJMPk &&
419*9880d681SAndroid Build Coastguard Worker getCondFromBranchOpc(I->getOpcode()) == AVRCC::COND_INVALID) {
420*9880d681SAndroid Build Coastguard Worker break;
421*9880d681SAndroid Build Coastguard Worker }
422*9880d681SAndroid Build Coastguard Worker
423*9880d681SAndroid Build Coastguard Worker // Remove the branch.
424*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
425*9880d681SAndroid Build Coastguard Worker I = MBB.end();
426*9880d681SAndroid Build Coastguard Worker ++Count;
427*9880d681SAndroid Build Coastguard Worker }
428*9880d681SAndroid Build Coastguard Worker
429*9880d681SAndroid Build Coastguard Worker return Count;
430*9880d681SAndroid Build Coastguard Worker }
431*9880d681SAndroid Build Coastguard Worker
ReverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const432*9880d681SAndroid Build Coastguard Worker bool AVRInstrInfo::ReverseBranchCondition(
433*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineOperand> &Cond) const {
434*9880d681SAndroid Build Coastguard Worker assert(Cond.size() == 1 && "Invalid AVR branch condition!");
435*9880d681SAndroid Build Coastguard Worker
436*9880d681SAndroid Build Coastguard Worker AVRCC::CondCodes CC = static_cast<AVRCC::CondCodes>(Cond[0].getImm());
437*9880d681SAndroid Build Coastguard Worker Cond[0].setImm(getOppositeCondition(CC));
438*9880d681SAndroid Build Coastguard Worker
439*9880d681SAndroid Build Coastguard Worker return false;
440*9880d681SAndroid Build Coastguard Worker }
441*9880d681SAndroid Build Coastguard Worker
GetInstSizeInBytes(const MachineInstr * MI) const442*9880d681SAndroid Build Coastguard Worker unsigned AVRInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
443*9880d681SAndroid Build Coastguard Worker unsigned Opcode = MI->getOpcode();
444*9880d681SAndroid Build Coastguard Worker
445*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
446*9880d681SAndroid Build Coastguard Worker // A regular instruction
447*9880d681SAndroid Build Coastguard Worker default: {
448*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &Desc = get(Opcode);
449*9880d681SAndroid Build Coastguard Worker return Desc.getSize();
450*9880d681SAndroid Build Coastguard Worker }
451*9880d681SAndroid Build Coastguard Worker case TargetOpcode::EH_LABEL:
452*9880d681SAndroid Build Coastguard Worker case TargetOpcode::IMPLICIT_DEF:
453*9880d681SAndroid Build Coastguard Worker case TargetOpcode::KILL:
454*9880d681SAndroid Build Coastguard Worker case TargetOpcode::DBG_VALUE:
455*9880d681SAndroid Build Coastguard Worker return 0;
456*9880d681SAndroid Build Coastguard Worker case TargetOpcode::INLINEASM: {
457*9880d681SAndroid Build Coastguard Worker const MachineFunction *MF = MI->getParent()->getParent();
458*9880d681SAndroid Build Coastguard Worker const AVRTargetMachine &TM = static_cast<const AVRTargetMachine&>(MF->getTarget());
459*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo();
460*9880d681SAndroid Build Coastguard Worker return TII.getInlineAsmLength(MI->getOperand(0).getSymbolName(),
461*9880d681SAndroid Build Coastguard Worker *TM.getMCAsmInfo());
462*9880d681SAndroid Build Coastguard Worker }
463*9880d681SAndroid Build Coastguard Worker }
464*9880d681SAndroid Build Coastguard Worker }
465*9880d681SAndroid Build Coastguard Worker
466*9880d681SAndroid Build Coastguard Worker } // end of namespace llvm
467