xref: /aosp_15_r20/external/llvm/lib/Target/AVR/AVRInstrInfo.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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