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