blob: 4a95fced446b2da59f8ea175a38d9166217b3aeb [file] [log] [blame]
Pete Couperus2d1f6d62017-08-24 15:40:33 +00001//===- ARCInstrInfo.cpp - ARC 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 ARC implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARCInstrInfo.h"
15#include "ARC.h"
16#include "ARCMachineFunctionInfo.h"
17#include "ARCSubtarget.h"
18#include "MCTargetDesc/ARCInfo.h"
19#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
21#include "llvm/CodeGen/MachineMemOperand.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/TargetRegistry.h"
24
25using namespace llvm;
26
27#define GET_INSTRINFO_CTOR_DTOR
28#include "ARCGenInstrInfo.inc"
29
30#define DEBUG_TYPE "arc-inst-info"
31// Pin the vtable to this file.
32void ARCInstrInfo::anchor() {}
33
34ARCInstrInfo::ARCInstrInfo()
35 : ARCGenInstrInfo(ARC::ADJCALLSTACKDOWN, ARC::ADJCALLSTACKUP), RI() {}
36
37static bool isZeroImm(const MachineOperand &Op) {
38 return Op.isImm() && Op.getImm() == 0;
39}
40
41static bool isLoad(int Opcode) {
42 return Opcode == ARC::LD_rs9 || Opcode == ARC::LDH_rs9 ||
43 Opcode == ARC::LDB_rs9;
44}
45
46static bool isStore(int Opcode) {
47 return Opcode == ARC::ST_rs9 || Opcode == ARC::STH_rs9 ||
48 Opcode == ARC::STB_rs9;
49}
50
51/// 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.
56unsigned ARCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
57 int &FrameIndex) const {
58 int Opcode = MI.getOpcode();
59 if (isLoad(Opcode)) {
60 if ((MI.getOperand(1).isFI()) && // is a stack slot
61 (MI.getOperand(2).isImm()) && // the imm is zero
62 (isZeroImm(MI.getOperand(2)))) {
63 FrameIndex = MI.getOperand(1).getIndex();
64 return MI.getOperand(0).getReg();
65 }
66 }
67 return 0;
68}
69
70/// If the specified machine instruction is a direct
71/// store to a stack slot, return the virtual or physical register number of
72/// the source reg along with the FrameIndex of the loaded stack slot. If
73/// not, return 0. This predicate must return 0 if the instruction has
74/// any side effects other than storing to the stack slot.
75unsigned ARCInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
76 int &FrameIndex) const {
77 int Opcode = MI.getOpcode();
78 if (isStore(Opcode)) {
79 if ((MI.getOperand(1).isFI()) && // is a stack slot
80 (MI.getOperand(2).isImm()) && // the imm is zero
81 (isZeroImm(MI.getOperand(2)))) {
82 FrameIndex = MI.getOperand(1).getIndex();
83 return MI.getOperand(0).getReg();
84 }
85 }
86 return 0;
87}
88
89/// Return the inverse of passed condition, i.e. turning COND_E to COND_NE.
90static ARCCC::CondCode GetOppositeBranchCondition(ARCCC::CondCode CC) {
91 switch (CC) {
92 default:
93 llvm_unreachable("Illegal condition code!");
94 case ARCCC::EQ:
95 return ARCCC::NE;
96 case ARCCC::NE:
97 return ARCCC::EQ;
98 case ARCCC::LO:
99 return ARCCC::HS;
100 case ARCCC::HS:
101 return ARCCC::LO;
102 case ARCCC::GT:
103 return ARCCC::LE;
104 case ARCCC::GE:
105 return ARCCC::LT;
Tatyana Krasnukha8979eea2018-01-17 17:58:28 +0000106 case ARCCC::VS:
107 return ARCCC::VC;
108 case ARCCC::VC:
109 return ARCCC::VS;
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000110 case ARCCC::LT:
111 return ARCCC::GE;
112 case ARCCC::LE:
113 return ARCCC::GT;
114 case ARCCC::HI:
115 return ARCCC::LS;
116 case ARCCC::LS:
117 return ARCCC::HI;
118 case ARCCC::NZ:
119 return ARCCC::Z;
120 case ARCCC::Z:
121 return ARCCC::NZ;
122 }
123}
124
125static bool isUncondBranchOpcode(int Opc) { return Opc == ARC::BR; }
126
127static bool isCondBranchOpcode(int Opc) {
128 return Opc == ARC::BRcc_rr_p || Opc == ARC::BRcc_ru6_p;
129}
130
131static bool isJumpOpcode(int Opc) { return Opc == ARC::J; }
132
133/// Analyze the branching code at the end of MBB, returning
134/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
135/// implemented for a target). Upon success, this returns false and returns
136/// with the following information in various cases:
137///
138/// 1. If this block ends with no branches (it just falls through to its succ)
139/// just return false, leaving TBB/FBB null.
140/// 2. If this block ends with only an unconditional branch, it sets TBB to be
141/// the destination block.
142/// 3. If this block ends with a conditional branch and it falls through to a
143/// successor block, it sets TBB to be the branch destination block and a
144/// list of operands that evaluate the condition. These operands can be
145/// passed to other TargetInstrInfo methods to create new branches.
146/// 4. If this block ends with a conditional branch followed by an
147/// unconditional branch, it returns the 'true' destination in TBB, the
148/// 'false' destination in FBB, and a list of operands that evaluate the
149/// condition. These operands can be passed to other TargetInstrInfo
150/// methods to create new branches.
151///
152/// Note that RemoveBranch and InsertBranch must be implemented to support
153/// cases where this method returns success.
154///
155/// If AllowModify is true, then this routine is allowed to modify the basic
156/// block (e.g. delete instructions after the unconditional branch).
157
158bool ARCInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
159 MachineBasicBlock *&TBB,
160 MachineBasicBlock *&FBB,
161 SmallVectorImpl<MachineOperand> &Cond,
162 bool AllowModify) const {
163 TBB = FBB = nullptr;
164 MachineBasicBlock::iterator I = MBB.end();
165 if (I == MBB.begin())
166 return false;
167 --I;
168
169 while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) {
170 // Flag to be raised on unanalyzeable instructions. This is useful in cases
171 // where we want to clean up on the end of the basic block before we bail
172 // out.
173 bool CantAnalyze = false;
174
175 // Skip over DEBUG values and predicated nonterminators.
176 while (I->isDebugValue() || !I->isTerminator()) {
177 if (I == MBB.begin())
178 return false;
179 --I;
180 }
181
182 if (isJumpOpcode(I->getOpcode())) {
183 // Indirect branches and jump tables can't be analyzed, but we still want
184 // to clean up any instructions at the tail of the basic block.
185 CantAnalyze = true;
186 } else if (isUncondBranchOpcode(I->getOpcode())) {
187 TBB = I->getOperand(0).getMBB();
188 } else if (isCondBranchOpcode(I->getOpcode())) {
189 // Bail out if we encounter multiple conditional branches.
190 if (!Cond.empty())
191 return true;
192
193 assert(!FBB && "FBB should have been null.");
194 FBB = TBB;
195 TBB = I->getOperand(0).getMBB();
196 Cond.push_back(I->getOperand(1));
197 Cond.push_back(I->getOperand(2));
198 Cond.push_back(I->getOperand(3));
199 } else if (I->isReturn()) {
200 // Returns can't be analyzed, but we should run cleanup.
201 CantAnalyze = !isPredicated(*I);
202 } else {
203 // We encountered other unrecognized terminator. Bail out immediately.
204 return true;
205 }
206
207 // Cleanup code - to be run for unpredicated unconditional branches and
208 // returns.
209 if (!isPredicated(*I) && (isUncondBranchOpcode(I->getOpcode()) ||
210 isJumpOpcode(I->getOpcode()) || I->isReturn())) {
211 // Forget any previous condition branch information - it no longer
212 // applies.
213 Cond.clear();
214 FBB = nullptr;
215
216 // If we can modify the function, delete everything below this
217 // unconditional branch.
218 if (AllowModify) {
219 MachineBasicBlock::iterator DI = std::next(I);
220 while (DI != MBB.end()) {
221 MachineInstr &InstToDelete = *DI;
222 ++DI;
223 InstToDelete.eraseFromParent();
224 }
225 }
226 }
227
228 if (CantAnalyze)
229 return true;
230
231 if (I == MBB.begin())
232 return false;
233
234 --I;
235 }
236
237 // We made it past the terminators without bailing out - we must have
238 // analyzed this branch successfully.
239 return false;
240}
241
242unsigned ARCInstrInfo::removeBranch(MachineBasicBlock &MBB,
243 int *BytesRemoved) const {
244 assert(!BytesRemoved && "Code size not handled");
245 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
246 if (I == MBB.end())
247 return 0;
248
249 if (!isUncondBranchOpcode(I->getOpcode()) &&
250 !isCondBranchOpcode(I->getOpcode()))
251 return 0;
252
253 // Remove the branch.
254 I->eraseFromParent();
255
256 I = MBB.end();
257
258 if (I == MBB.begin())
259 return 1;
260 --I;
261 if (!isCondBranchOpcode(I->getOpcode()))
262 return 1;
263
264 // Remove the branch.
265 I->eraseFromParent();
266 return 2;
267}
268
269void ARCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
270 MachineBasicBlock::iterator I,
271 const DebugLoc &dl, unsigned DestReg,
272 unsigned SrcReg, bool KillSrc) const {
273 assert(ARC::GPR32RegClass.contains(SrcReg) &&
274 "Only GPR32 src copy supported.");
275 assert(ARC::GPR32RegClass.contains(DestReg) &&
276 "Only GPR32 dest copy supported.");
277 BuildMI(MBB, I, dl, get(ARC::MOV_rr), DestReg)
278 .addReg(SrcReg, getKillRegState(KillSrc));
279}
280
281void ARCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
282 MachineBasicBlock::iterator I,
283 unsigned SrcReg, bool isKill,
284 int FrameIndex,
285 const TargetRegisterClass *RC,
286 const TargetRegisterInfo *TRI) const {
287 DebugLoc dl = MBB.findDebugLoc(I);
288 MachineFunction &MF = *MBB.getParent();
289 MachineFrameInfo &MFI = MF.getFrameInfo();
290 unsigned Align = MFI.getObjectAlignment(FrameIndex);
291
292 MachineMemOperand *MMO = MF.getMachineMemOperand(
293 MachinePointerInfo::getFixedStack(MF, FrameIndex),
294 MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex), Align);
295
296 assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
297 assert(TRI->getSpillSize(*RC) == 4 &&
298 "Only support 4-byte stores to stack now.");
299 assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
300 "Only support GPR32 stores to stack now.");
Francis Visoiu Mistrih9d419d32017-11-28 12:42:37 +0000301 DEBUG(dbgs() << "Created store reg=" << printReg(SrcReg, TRI)
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000302 << " to FrameIndex=" << FrameIndex << "\n");
303 BuildMI(MBB, I, dl, get(ARC::ST_rs9))
304 .addReg(SrcReg, getKillRegState(isKill))
305 .addFrameIndex(FrameIndex)
306 .addImm(0)
307 .addMemOperand(MMO);
308}
309
310void ARCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
311 MachineBasicBlock::iterator I,
312 unsigned DestReg, int FrameIndex,
313 const TargetRegisterClass *RC,
314 const TargetRegisterInfo *TRI) const {
315 DebugLoc dl = MBB.findDebugLoc(I);
316 MachineFunction &MF = *MBB.getParent();
317 MachineFrameInfo &MFI = MF.getFrameInfo();
318 unsigned Align = MFI.getObjectAlignment(FrameIndex);
319 MachineMemOperand *MMO = MF.getMachineMemOperand(
320 MachinePointerInfo::getFixedStack(MF, FrameIndex),
321 MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex), Align);
322
323 assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
324 assert(TRI->getSpillSize(*RC) == 4 &&
325 "Only support 4-byte loads from stack now.");
326 assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
327 "Only support GPR32 stores to stack now.");
Francis Visoiu Mistrih9d419d32017-11-28 12:42:37 +0000328 DEBUG(dbgs() << "Created load reg=" << printReg(DestReg, TRI)
Pete Couperus2d1f6d62017-08-24 15:40:33 +0000329 << " from FrameIndex=" << FrameIndex << "\n");
330 BuildMI(MBB, I, dl, get(ARC::LD_rs9))
331 .addReg(DestReg, RegState::Define)
332 .addFrameIndex(FrameIndex)
333 .addImm(0)
334 .addMemOperand(MMO);
335}
336
337/// Return the inverse opcode of the specified Branch instruction.
338bool ARCInstrInfo::reverseBranchCondition(
339 SmallVectorImpl<MachineOperand> &Cond) const {
340 assert((Cond.size() == 3) && "Invalid ARC branch condition!");
341 Cond[2].setImm(GetOppositeBranchCondition((ARCCC::CondCode)Cond[2].getImm()));
342 return false;
343}
344
345MachineBasicBlock::iterator
346ARCInstrInfo::loadImmediate(MachineBasicBlock &MBB,
347 MachineBasicBlock::iterator MI, unsigned Reg,
348 uint64_t Value) const {
349 DebugLoc dl = MBB.findDebugLoc(MI);
350 if (isInt<12>(Value)) {
351 return BuildMI(MBB, MI, dl, get(ARC::MOV_rs12), Reg)
352 .addImm(Value)
353 .getInstr();
354 }
355 llvm_unreachable("Need Arc long immediate instructions.");
356}
357
358unsigned ARCInstrInfo::insertBranch(MachineBasicBlock &MBB,
359 MachineBasicBlock *TBB,
360 MachineBasicBlock *FBB,
361 ArrayRef<MachineOperand> Cond,
362 const DebugLoc &dl, int *BytesAdded) const {
363 assert(!BytesAdded && "Code size not handled.");
364
365 // Shouldn't be a fall through.
366 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
367 assert((Cond.size() == 3 || Cond.size() == 0) &&
368 "ARC branch conditions have two components!");
369
370 if (Cond.empty()) {
371 BuildMI(&MBB, dl, get(ARC::BR)).addMBB(TBB);
372 return 1;
373 }
374 int BccOpc = Cond[1].isImm() ? ARC::BRcc_ru6_p : ARC::BRcc_rr_p;
375 MachineInstrBuilder MIB = BuildMI(&MBB, dl, get(BccOpc));
376 MIB.addMBB(TBB);
377 for (unsigned i = 0; i < 3; i++) {
378 MIB.add(Cond[i]);
379 }
380
381 // One-way conditional branch.
382 if (!FBB) {
383 return 1;
384 }
385
386 // Two-way conditional branch.
387 BuildMI(&MBB, dl, get(ARC::BR)).addMBB(FBB);
388 return 2;
389}
390
391unsigned ARCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
392 if (MI.getOpcode() == TargetOpcode::INLINEASM) {
393 const MachineFunction *MF = MI.getParent()->getParent();
394 const char *AsmStr = MI.getOperand(0).getSymbolName();
395 return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
396 }
397 return MI.getDesc().getSize();
398}