]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/lib/Target/XCore/XCoreInstrInfo.cpp
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / lib / Target / XCore / XCoreInstrInfo.cpp
1 //===- XCoreInstrInfo.cpp - XCore 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 XCore implementation of the TargetInstrInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "XCoreMachineFunctionInfo.h"
15 #include "XCoreInstrInfo.h"
16 #include "XCore.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineLocation.h"
21 #include "llvm/Target/TargetRegistry.h"
22 #include "llvm/ADT/STLExtras.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/ErrorHandling.h"
25
26 #define GET_INSTRINFO_CTOR
27 #include "XCoreGenInstrInfo.inc"
28
29 namespace llvm {
30 namespace XCore {
31
32   // XCore Condition Codes
33   enum CondCode {
34     COND_TRUE,
35     COND_FALSE,
36     COND_INVALID
37   };
38 }
39 }
40
41 using namespace llvm;
42
43 XCoreInstrInfo::XCoreInstrInfo()
44   : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
45     RI(*this) {
46 }
47
48 static bool isZeroImm(const MachineOperand &op) {
49   return op.isImm() && op.getImm() == 0;
50 }
51
52 /// isLoadFromStackSlot - If the specified machine instruction is a direct
53 /// load from a stack slot, return the virtual or physical register number of
54 /// the destination along with the FrameIndex of the loaded stack slot.  If
55 /// not, return 0.  This predicate must return 0 if the instruction has
56 /// any side effects other than loading from the stack slot.
57 unsigned
58 XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const{
59   int Opcode = MI->getOpcode();
60   if (Opcode == XCore::LDWFI) 
61   {
62     if ((MI->getOperand(1).isFI()) && // is a stack slot
63         (MI->getOperand(2).isImm()) &&  // the imm is zero
64         (isZeroImm(MI->getOperand(2)))) 
65     {
66       FrameIndex = MI->getOperand(1).getIndex();
67       return MI->getOperand(0).getReg();
68     }
69   }
70   return 0;
71 }
72   
73   /// isStoreToStackSlot - If the specified machine instruction is a direct
74   /// store to a stack slot, return the virtual or physical register number of
75   /// the source reg along with the FrameIndex of the loaded stack slot.  If
76   /// not, return 0.  This predicate must return 0 if the instruction has
77   /// any side effects other than storing to the stack slot.
78 unsigned
79 XCoreInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
80                                    int &FrameIndex) const {
81   int Opcode = MI->getOpcode();
82   if (Opcode == XCore::STWFI)
83   {
84     if ((MI->getOperand(1).isFI()) && // is a stack slot
85         (MI->getOperand(2).isImm()) &&  // the imm is zero
86         (isZeroImm(MI->getOperand(2))))
87     {
88       FrameIndex = MI->getOperand(1).getIndex();
89       return MI->getOperand(0).getReg();
90     }
91   }
92   return 0;
93 }
94
95 //===----------------------------------------------------------------------===//
96 // Branch Analysis
97 //===----------------------------------------------------------------------===//
98
99 static inline bool IsBRU(unsigned BrOpc) {
100   return BrOpc == XCore::BRFU_u6
101       || BrOpc == XCore::BRFU_lu6
102       || BrOpc == XCore::BRBU_u6
103       || BrOpc == XCore::BRBU_lu6;
104 }
105
106 static inline bool IsBRT(unsigned BrOpc) {
107   return BrOpc == XCore::BRFT_ru6
108       || BrOpc == XCore::BRFT_lru6
109       || BrOpc == XCore::BRBT_ru6
110       || BrOpc == XCore::BRBT_lru6;
111 }
112
113 static inline bool IsBRF(unsigned BrOpc) {
114   return BrOpc == XCore::BRFF_ru6
115       || BrOpc == XCore::BRFF_lru6
116       || BrOpc == XCore::BRBF_ru6
117       || BrOpc == XCore::BRBF_lru6;
118 }
119
120 static inline bool IsCondBranch(unsigned BrOpc) {
121   return IsBRF(BrOpc) || IsBRT(BrOpc);
122 }
123
124 static inline bool IsBR_JT(unsigned BrOpc) {
125   return BrOpc == XCore::BR_JT
126       || BrOpc == XCore::BR_JT32;
127 }
128
129 /// GetCondFromBranchOpc - Return the XCore CC that matches 
130 /// the correspondent Branch instruction opcode.
131 static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc) 
132 {
133   if (IsBRT(BrOpc)) {
134     return XCore::COND_TRUE;
135   } else if (IsBRF(BrOpc)) {
136     return XCore::COND_FALSE;
137   } else {
138     return XCore::COND_INVALID;
139   }
140 }
141
142 /// GetCondBranchFromCond - Return the Branch instruction
143 /// opcode that matches the cc.
144 static inline unsigned GetCondBranchFromCond(XCore::CondCode CC) 
145 {
146   switch (CC) {
147   default: llvm_unreachable("Illegal condition code!");
148   case XCore::COND_TRUE   : return XCore::BRFT_lru6;
149   case XCore::COND_FALSE  : return XCore::BRFF_lru6;
150   }
151 }
152
153 /// GetOppositeBranchCondition - Return the inverse of the specified 
154 /// condition, e.g. turning COND_E to COND_NE.
155 static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
156 {
157   switch (CC) {
158   default: llvm_unreachable("Illegal condition code!");
159   case XCore::COND_TRUE   : return XCore::COND_FALSE;
160   case XCore::COND_FALSE  : return XCore::COND_TRUE;
161   }
162 }
163
164 /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
165 /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
166 /// implemented for a target).  Upon success, this returns false and returns
167 /// with the following information in various cases:
168 ///
169 /// 1. If this block ends with no branches (it just falls through to its succ)
170 ///    just return false, leaving TBB/FBB null.
171 /// 2. If this block ends with only an unconditional branch, it sets TBB to be
172 ///    the destination block.
173 /// 3. If this block ends with an conditional branch and it falls through to
174 ///    an successor block, it sets TBB to be the branch destination block and a
175 ///    list of operands that evaluate the condition. These
176 ///    operands can be passed to other TargetInstrInfo methods to create new
177 ///    branches.
178 /// 4. If this block ends with an conditional branch and an unconditional
179 ///    block, it returns the 'true' destination in TBB, the 'false' destination
180 ///    in FBB, and a list of operands that evaluate the condition. These
181 ///    operands can be passed to other TargetInstrInfo methods to create new
182 ///    branches.
183 ///
184 /// Note that RemoveBranch and InsertBranch must be implemented to support
185 /// cases where this method returns success.
186 ///
187 bool
188 XCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
189                               MachineBasicBlock *&FBB,
190                               SmallVectorImpl<MachineOperand> &Cond,
191                               bool AllowModify) const {
192   // If the block has no terminators, it just falls into the block after it.
193   MachineBasicBlock::iterator I = MBB.end();
194   if (I == MBB.begin())
195     return false;
196   --I;
197   while (I->isDebugValue()) {
198     if (I == MBB.begin())
199       return false;
200     --I;
201   }
202   if (!isUnpredicatedTerminator(I))
203     return false;
204
205   // Get the last instruction in the block.
206   MachineInstr *LastInst = I;
207   
208   // If there is only one terminator instruction, process it.
209   if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
210     if (IsBRU(LastInst->getOpcode())) {
211       TBB = LastInst->getOperand(0).getMBB();
212       return false;
213     }
214     
215     XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
216     if (BranchCode == XCore::COND_INVALID)
217       return true;  // Can't handle indirect branch.
218     
219     // Conditional branch
220     // Block ends with fall-through condbranch.
221
222     TBB = LastInst->getOperand(1).getMBB();
223     Cond.push_back(MachineOperand::CreateImm(BranchCode));
224     Cond.push_back(LastInst->getOperand(0));
225     return false;
226   }
227   
228   // Get the instruction before it if it's a terminator.
229   MachineInstr *SecondLastInst = I;
230
231   // If there are three terminators, we don't know what sort of block this is.
232   if (SecondLastInst && I != MBB.begin() &&
233       isUnpredicatedTerminator(--I))
234     return true;
235   
236   unsigned SecondLastOpc    = SecondLastInst->getOpcode();
237   XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
238   
239   // If the block ends with conditional branch followed by unconditional,
240   // handle it.
241   if (BranchCode != XCore::COND_INVALID
242     && IsBRU(LastInst->getOpcode())) {
243
244     TBB = SecondLastInst->getOperand(1).getMBB();
245     Cond.push_back(MachineOperand::CreateImm(BranchCode));
246     Cond.push_back(SecondLastInst->getOperand(0));
247
248     FBB = LastInst->getOperand(0).getMBB();
249     return false;
250   }
251   
252   // If the block ends with two unconditional branches, handle it.  The second
253   // one is not executed, so remove it.
254   if (IsBRU(SecondLastInst->getOpcode()) && 
255       IsBRU(LastInst->getOpcode())) {
256     TBB = SecondLastInst->getOperand(0).getMBB();
257     I = LastInst;
258     if (AllowModify)
259       I->eraseFromParent();
260     return false;
261   }
262
263   // Likewise if it ends with a branch table followed by an unconditional branch.
264   if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
265     I = LastInst;
266     if (AllowModify)
267       I->eraseFromParent();
268     return true;
269   }
270
271   // Otherwise, can't handle this.
272   return true;
273 }
274
275 unsigned
276 XCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
277                              MachineBasicBlock *FBB,
278                              const SmallVectorImpl<MachineOperand> &Cond,
279                              DebugLoc DL)const{
280   // Shouldn't be a fall through.
281   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
282   assert((Cond.size() == 2 || Cond.size() == 0) &&
283          "Unexpected number of components!");
284   
285   if (FBB == 0) { // One way branch.
286     if (Cond.empty()) {
287       // Unconditional branch
288       BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
289     } else {
290       // Conditional branch.
291       unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
292       BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
293                              .addMBB(TBB);
294     }
295     return 1;
296   }
297   
298   // Two-way Conditional branch.
299   assert(Cond.size() == 2 && "Unexpected number of components!");
300   unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
301   BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
302                          .addMBB(TBB);
303   BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
304   return 2;
305 }
306
307 unsigned
308 XCoreInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
309   MachineBasicBlock::iterator I = MBB.end();
310   if (I == MBB.begin()) return 0;
311   --I;
312   while (I->isDebugValue()) {
313     if (I == MBB.begin())
314       return 0;
315     --I;
316   }
317   if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
318     return 0;
319   
320   // Remove the branch.
321   I->eraseFromParent();
322   
323   I = MBB.end();
324
325   if (I == MBB.begin()) return 1;
326   --I;
327   if (!IsCondBranch(I->getOpcode()))
328     return 1;
329   
330   // Remove the branch.
331   I->eraseFromParent();
332   return 2;
333 }
334
335 void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
336                                  MachineBasicBlock::iterator I, DebugLoc DL,
337                                  unsigned DestReg, unsigned SrcReg,
338                                  bool KillSrc) const {
339   bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
340   bool GRSrc  = XCore::GRRegsRegClass.contains(SrcReg);
341
342   if (GRDest && GRSrc) {
343     BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
344       .addReg(SrcReg, getKillRegState(KillSrc))
345       .addImm(0);
346     return;
347   }
348   
349   if (GRDest && SrcReg == XCore::SP) {
350     BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
351     return;
352   }
353
354   if (DestReg == XCore::SP && GRSrc) {
355     BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
356       .addReg(SrcReg, getKillRegState(KillSrc));
357     return;
358   }
359   llvm_unreachable("Impossible reg-to-reg copy");
360 }
361
362 void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
363                                          MachineBasicBlock::iterator I,
364                                          unsigned SrcReg, bool isKill,
365                                          int FrameIndex,
366                                          const TargetRegisterClass *RC,
367                                          const TargetRegisterInfo *TRI) const
368 {
369   DebugLoc DL;
370   if (I != MBB.end()) DL = I->getDebugLoc();
371   BuildMI(MBB, I, DL, get(XCore::STWFI))
372     .addReg(SrcReg, getKillRegState(isKill))
373     .addFrameIndex(FrameIndex)
374     .addImm(0);
375 }
376
377 void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
378                                           MachineBasicBlock::iterator I,
379                                           unsigned DestReg, int FrameIndex,
380                                           const TargetRegisterClass *RC,
381                                           const TargetRegisterInfo *TRI) const
382 {
383   DebugLoc DL;
384   if (I != MBB.end()) DL = I->getDebugLoc();
385   BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
386     .addFrameIndex(FrameIndex)
387     .addImm(0);
388 }
389
390 /// ReverseBranchCondition - Return the inverse opcode of the 
391 /// specified Branch instruction.
392 bool XCoreInstrInfo::
393 ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
394   assert((Cond.size() == 2) && 
395           "Invalid XCore branch condition!");
396   Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
397   return false;
398 }