LLVM 22.0.0git
ARCInstrInfo.cpp
Go to the documentation of this file.
1//===- ARCInstrInfo.cpp - ARC Instruction Information -----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the ARC implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ARCInstrInfo.h"
14#include "ARC.h"
16#include "ARCSubtarget.h"
22#include "llvm/Support/Debug.h"
23
24using namespace llvm;
25
26#define GET_INSTRINFO_CTOR_DTOR
27#include "ARCGenInstrInfo.inc"
28
29#define DEBUG_TYPE "arc-inst-info"
30
33 PreInc = 1,
36};
37
42
43// Pin the vtable to this file.
44void ARCInstrInfo::anchor() {}
45
47 : ARCGenInstrInfo(ST, RI, ARC::ADJCALLSTACKDOWN, ARC::ADJCALLSTACKUP),
48 RI(ST) {}
49
50static bool isZeroImm(const MachineOperand &Op) {
51 return Op.isImm() && Op.getImm() == 0;
52}
53
54static bool isLoad(int Opcode) {
55 return Opcode == ARC::LD_rs9 || Opcode == ARC::LDH_rs9 ||
56 Opcode == ARC::LDB_rs9;
57}
58
59static bool isStore(int Opcode) {
60 return Opcode == ARC::ST_rs9 || Opcode == ARC::STH_rs9 ||
61 Opcode == ARC::STB_rs9;
62}
63
64/// If the specified machine instruction is a direct
65/// load from a stack slot, return the virtual or physical register number of
66/// the destination along with the FrameIndex of the loaded stack slot. If
67/// not, return 0. This predicate must return 0 if the instruction has
68/// any side effects other than loading from the stack slot.
70 int &FrameIndex) const {
71 int Opcode = MI.getOpcode();
72 if (isLoad(Opcode)) {
73 if ((MI.getOperand(1).isFI()) && // is a stack slot
74 (MI.getOperand(2).isImm()) && // the imm is zero
75 (isZeroImm(MI.getOperand(2)))) {
76 FrameIndex = MI.getOperand(1).getIndex();
77 return MI.getOperand(0).getReg();
78 }
79 }
80 return 0;
81}
82
83/// If the specified machine instruction is a direct
84/// store to a stack slot, return the virtual or physical register number of
85/// the source reg along with the FrameIndex of the loaded stack slot. If
86/// not, return 0. This predicate must return 0 if the instruction has
87/// any side effects other than storing to the stack slot.
89 int &FrameIndex) const {
90 int Opcode = MI.getOpcode();
91 if (isStore(Opcode)) {
92 if ((MI.getOperand(1).isFI()) && // is a stack slot
93 (MI.getOperand(2).isImm()) && // the imm is zero
94 (isZeroImm(MI.getOperand(2)))) {
95 FrameIndex = MI.getOperand(1).getIndex();
96 return MI.getOperand(0).getReg();
97 }
98 }
99 return 0;
100}
101
102/// Return the inverse of passed condition, i.e. turning COND_E to COND_NE.
104 switch (CC) {
105 default:
106 llvm_unreachable("Illegal condition code!");
107 case ARCCC::EQ:
108 return ARCCC::NE;
109 case ARCCC::NE:
110 return ARCCC::EQ;
111 case ARCCC::LO:
112 return ARCCC::HS;
113 case ARCCC::HS:
114 return ARCCC::LO;
115 case ARCCC::GT:
116 return ARCCC::LE;
117 case ARCCC::GE:
118 return ARCCC::LT;
119 case ARCCC::VS:
120 return ARCCC::VC;
121 case ARCCC::VC:
122 return ARCCC::VS;
123 case ARCCC::LT:
124 return ARCCC::GE;
125 case ARCCC::LE:
126 return ARCCC::GT;
127 case ARCCC::HI:
128 return ARCCC::LS;
129 case ARCCC::LS:
130 return ARCCC::HI;
131 case ARCCC::NZ:
132 return ARCCC::Z;
133 case ARCCC::Z:
134 return ARCCC::NZ;
135 }
136}
137
138static bool isUncondBranchOpcode(int Opc) { return Opc == ARC::BR; }
139
140static bool isCondBranchOpcode(int Opc) {
141 return Opc == ARC::BRcc_rr_p || Opc == ARC::BRcc_ru6_p;
142}
143
144static bool isJumpOpcode(int Opc) { return Opc == ARC::J; }
145
146/// Analyze the branching code at the end of MBB, returning
147/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
148/// implemented for a target). Upon success, this returns false and returns
149/// with the following information in various cases:
150///
151/// 1. If this block ends with no branches (it just falls through to its succ)
152/// just return false, leaving TBB/FBB null.
153/// 2. If this block ends with only an unconditional branch, it sets TBB to be
154/// the destination block.
155/// 3. If this block ends with a conditional branch and it falls through to a
156/// successor block, it sets TBB to be the branch destination block and a
157/// list of operands that evaluate the condition. These operands can be
158/// passed to other TargetInstrInfo methods to create new branches.
159/// 4. If this block ends with a conditional branch followed by an
160/// unconditional branch, it returns the 'true' destination in TBB, the
161/// 'false' destination in FBB, and a list of operands that evaluate the
162/// condition. These operands can be passed to other TargetInstrInfo
163/// methods to create new branches.
164///
165/// Note that RemoveBranch and insertBranch must be implemented to support
166/// cases where this method returns success.
167///
168/// If AllowModify is true, then this routine is allowed to modify the basic
169/// block (e.g. delete instructions after the unconditional branch).
170
173 MachineBasicBlock *&FBB,
175 bool AllowModify) const {
176 TBB = FBB = nullptr;
178 if (I == MBB.begin())
179 return false;
180 --I;
181
182 while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) {
183 // Flag to be raised on unanalyzeable instructions. This is useful in cases
184 // where we want to clean up on the end of the basic block before we bail
185 // out.
186 bool CantAnalyze = false;
187
188 // Skip over DEBUG values and predicated nonterminators.
189 while (I->isDebugInstr() || !I->isTerminator()) {
190 if (I == MBB.begin())
191 return false;
192 --I;
193 }
194
195 if (isJumpOpcode(I->getOpcode())) {
196 // Indirect branches and jump tables can't be analyzed, but we still want
197 // to clean up any instructions at the tail of the basic block.
198 CantAnalyze = true;
199 } else if (isUncondBranchOpcode(I->getOpcode())) {
200 TBB = I->getOperand(0).getMBB();
201 } else if (isCondBranchOpcode(I->getOpcode())) {
202 // Bail out if we encounter multiple conditional branches.
203 if (!Cond.empty())
204 return true;
205
206 assert(!FBB && "FBB should have been null.");
207 FBB = TBB;
208 TBB = I->getOperand(0).getMBB();
209 Cond.push_back(I->getOperand(1));
210 Cond.push_back(I->getOperand(2));
211 Cond.push_back(I->getOperand(3));
212 } else if (I->isReturn()) {
213 // Returns can't be analyzed, but we should run cleanup.
214 CantAnalyze = !isPredicated(*I);
215 } else {
216 // We encountered other unrecognized terminator. Bail out immediately.
217 return true;
218 }
219
220 // Cleanup code - to be run for unpredicated unconditional branches and
221 // returns.
222 if (!isPredicated(*I) && (isUncondBranchOpcode(I->getOpcode()) ||
223 isJumpOpcode(I->getOpcode()) || I->isReturn())) {
224 // Forget any previous condition branch information - it no longer
225 // applies.
226 Cond.clear();
227 FBB = nullptr;
228
229 // If we can modify the function, delete everything below this
230 // unconditional branch.
231 if (AllowModify) {
232 MachineBasicBlock::iterator DI = std::next(I);
233 while (DI != MBB.end()) {
234 MachineInstr &InstToDelete = *DI;
235 ++DI;
236 InstToDelete.eraseFromParent();
237 }
238 }
239 }
240
241 if (CantAnalyze)
242 return true;
243
244 if (I == MBB.begin())
245 return false;
246
247 --I;
248 }
249
250 // We made it past the terminators without bailing out - we must have
251 // analyzed this branch successfully.
252 return false;
253}
254
256 int *BytesRemoved) const {
257 assert(!BytesRemoved && "Code size not handled");
258 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
259 if (I == MBB.end())
260 return 0;
261
262 if (!isUncondBranchOpcode(I->getOpcode()) &&
263 !isCondBranchOpcode(I->getOpcode()))
264 return 0;
265
266 // Remove the branch.
267 I->eraseFromParent();
268
269 I = MBB.end();
270
271 if (I == MBB.begin())
272 return 1;
273 --I;
274 if (!isCondBranchOpcode(I->getOpcode()))
275 return 1;
276
277 // Remove the branch.
278 I->eraseFromParent();
279 return 2;
280}
281
284 const DebugLoc &DL, Register DestReg,
285 Register SrcReg, bool KillSrc,
286 bool RenamableDest, bool RenamableSrc) const {
287 assert(ARC::GPR32RegClass.contains(SrcReg) &&
288 "Only GPR32 src copy supported.");
289 assert(ARC::GPR32RegClass.contains(DestReg) &&
290 "Only GPR32 dest copy supported.");
291 BuildMI(MBB, I, DL, get(ARC::MOV_rr), DestReg)
292 .addReg(SrcReg, getKillRegState(KillSrc));
293}
294
297 bool IsKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
298 MachineInstr::MIFlag Flags) const {
299 DebugLoc DL = MBB.findDebugLoc(I);
300 MachineFunction &MF = *MBB.getParent();
301 MachineFrameInfo &MFI = MF.getFrameInfo();
302
304 MachinePointerInfo::getFixedStack(MF, FrameIndex),
306 MFI.getObjectAlign(FrameIndex));
307
308 assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
309 assert(TRI.getSpillSize(*RC) == 4 &&
310 "Only support 4-byte stores to stack now.");
311 assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
312 "Only support GPR32 stores to stack now.");
313 LLVM_DEBUG(dbgs() << "Created store reg=" << printReg(SrcReg, &TRI)
314 << " to FrameIndex=" << FrameIndex << "\n");
315 BuildMI(MBB, I, DL, get(ARC::ST_rs9))
316 .addReg(SrcReg, getKillRegState(IsKill))
317 .addFrameIndex(FrameIndex)
318 .addImm(0)
319 .addMemOperand(MMO);
320}
321
324 Register DestReg, int FrameIndex,
325 const TargetRegisterClass *RC,
326 Register VReg,
327 MachineInstr::MIFlag Flags) const {
328 DebugLoc DL = MBB.findDebugLoc(I);
329 MachineFunction &MF = *MBB.getParent();
330 MachineFrameInfo &MFI = MF.getFrameInfo();
332 MachinePointerInfo::getFixedStack(MF, FrameIndex),
334 MFI.getObjectAlign(FrameIndex));
335
336 assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
337 assert(TRI.getSpillSize(*RC) == 4 &&
338 "Only support 4-byte loads from stack now.");
339 assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
340 "Only support GPR32 stores to stack now.");
341 LLVM_DEBUG(dbgs() << "Created load reg=" << printReg(DestReg, &TRI)
342 << " from FrameIndex=" << FrameIndex << "\n");
343 BuildMI(MBB, I, DL, get(ARC::LD_rs9))
344 .addReg(DestReg, RegState::Define)
345 .addFrameIndex(FrameIndex)
346 .addImm(0)
347 .addMemOperand(MMO);
348}
349
350/// Return the inverse opcode of the specified Branch instruction.
353 assert((Cond.size() == 3) && "Invalid ARC branch condition!");
355 return false;
356}
357
360 MachineBasicBlock::iterator MI, unsigned Reg,
361 uint64_t Value) const {
362 DebugLoc DL = MBB.findDebugLoc(MI);
363 if (isInt<12>(Value)) {
364 return BuildMI(MBB, MI, DL, get(ARC::MOV_rs12), Reg)
365 .addImm(Value)
366 .getInstr();
367 }
368 llvm_unreachable("Need Arc long immediate instructions.");
369}
370
375 const DebugLoc &DL, int *BytesAdded) const {
376 assert(!BytesAdded && "Code size not handled.");
377
378 // Shouldn't be a fall through.
379 assert(TBB && "insertBranch must not be told to insert a fallthrough");
380 assert((Cond.size() == 3 || Cond.size() == 0) &&
381 "ARC branch conditions have two components!");
382
383 if (Cond.empty()) {
384 BuildMI(&MBB, DL, get(ARC::BR)).addMBB(TBB);
385 return 1;
386 }
387 int BccOpc = Cond[1].isImm() ? ARC::BRcc_ru6_p : ARC::BRcc_rr_p;
388 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(BccOpc));
389 MIB.addMBB(TBB);
390 for (unsigned i = 0; i < 3; i++) {
391 MIB.add(Cond[i]);
392 }
393
394 // One-way conditional branch.
395 if (!FBB) {
396 return 1;
397 }
398
399 // Two-way conditional branch.
400 BuildMI(&MBB, DL, get(ARC::BR)).addMBB(FBB);
401 return 2;
402}
403
405 if (MI.isInlineAsm()) {
406 const MachineFunction *MF = MI.getParent()->getParent();
407 const char *AsmStr = MI.getOperand(0).getSymbolName();
408 return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
409 }
410 return MI.getDesc().getSize();
411}
412
414 const MCInstrDesc &MID = MI.getDesc();
415 const uint64_t F = MID.TSFlags;
416 return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PostInc;
417}
418
420 const MCInstrDesc &MID = MI.getDesc();
421 const uint64_t F = MID.TSFlags;
422 return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PreInc;
423}
424
426 unsigned &BasePos,
427 unsigned &OffsetPos) const {
428 if (!MI.mayLoad() && !MI.mayStore())
429 return false;
430
431 BasePos = 1;
432 OffsetPos = 2;
433
435 BasePos++;
436 OffsetPos++;
437 }
438
439 if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm())
440 return false;
441
442 return true;
443}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
TSFlagsConstants
@ TSF_AddModeMask
@ TSF_AddrModeOff
AddrIncType
@ PostInc
@ PreInc
@ Scaled
@ NoAddInc
static bool isLoad(int Opcode)
static ARCCC::CondCode getOppositeBranchCondition(ARCCC::CondCode CC)
Return the inverse of passed condition, i.e. turning COND_E to COND_NE.
static bool isStore(int Opcode)
static bool isZeroImm(const MachineOperand &Op)
static bool isJumpOpcode(int Opc)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
#define LLVM_DEBUG(...)
Definition Debug.h:114
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &, int *BytesAdded=nullptr) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
virtual bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos, unsigned &OffsetPos) const override
bool isPostIncrement(const MachineInstr &MI) const override
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
If the specified machine instruction is a direct store to a stack slot, return the virtual or physica...
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool IsKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
MachineBasicBlock::iterator loadImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Reg, uint64_t Value) const
ARCInstrInfo(const ARCSubtarget &)
bool isPreIncrement(const MachineInstr &MI) const
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
If the specified machine instruction is a direct load from a stack slot, return the virtual or physic...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Return the inverse opcode of the specified Branch instruction.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
A debug info location.
Definition DebugLoc.h:124
Describe properties that are true of each instruction in the target description file.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Define
Register definition.
This is an optimization pass for GlobalISel generic memory operations.
static bool isCondBranchOpcode(int Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
unsigned getKillRegState(bool B)
DWARFExpression::Operation Op
static bool isUncondBranchOpcode(int Opc)
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.