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