LLVM: lib/Target/Sparc/SparcInstrInfo.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
23
24using namespace llvm;
25
26#define GET_INSTRINFO_CTOR_DTOR
27#include "SparcGenInstrInfo.inc"
28
31 cl::desc("Restrict range of BPcc/FBPfcc instructions (DEBUG)"));
32
35 cl::desc("Restrict range of BPr instructions (DEBUG)"));
36
37
38void SparcInstrInfo::anchor() {}
39
41 : SparcGenInstrInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), RI(),
42 Subtarget(ST) {}
43
44
45
46
47
48
50 int &FrameIndex) const {
51 if (MI.getOpcode() == SP::LDri || MI.getOpcode() == SP::LDXri ||
52 MI.getOpcode() == SP::LDFri || MI.getOpcode() == SP::LDDFri ||
53 MI.getOpcode() == SP::LDQFri) {
54 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
55 MI.getOperand(2).getImm() == 0) {
56 FrameIndex = MI.getOperand(1).getIndex();
57 return MI.getOperand(0).getReg();
58 }
59 }
60 return 0;
61}
62
63
64
65
66
67
69 int &FrameIndex) const {
70 if (MI.getOpcode() == SP::STri || MI.getOpcode() == SP::STXri ||
71 MI.getOpcode() == SP::STFri || MI.getOpcode() == SP::STDFri ||
72 MI.getOpcode() == SP::STQFri) {
73 if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
74 MI.getOperand(1).getImm() == 0) {
75 FrameIndex = MI.getOperand(0).getIndex();
76 return MI.getOperand(2).getReg();
77 }
78 }
79 return 0;
80}
81
83{
84 switch(CC) {
101
118
135
136
137
138
139 llvm_unreachable("Meaningless inversion of co-processor cond code");
140
155 }
157}
158
160
162 return Opc == SP::BCOND || Opc == SP::BPICC || Opc == SP::BPICCA ||
163 Opc == SP::BPICCNT || Opc == SP::BPICCANT;
164}
165
167 return Opc == SP::BPXCC || Opc == SP::BPXCCA || Opc == SP::BPXCCNT ||
168 Opc == SP::BPXCCANT;
169}
170
172 return Opc == SP::BPR || Opc == SP::BPRA || Opc == SP::BPRNT ||
173 Opc == SP::BPRANT;
174}
175
177 return Opc == SP::FBCOND || Opc == SP::FBCONDA || Opc == SP::FBCOND_V9 ||
178 Opc == SP::FBCONDA_V9;
179}
180
184}
185
187 return Opc == SP::BINDrr || Opc == SP::BINDri;
188}
189
192 unsigned Opc = LastInst->getOpcode();
194
195
196
199
200
201
205 }
206
208}
209
212 switch (MI.getOpcode()) {
213 default:
215 case SP::BA:
216 case SP::BCOND:
217 case SP::BCONDA:
218 case SP::FBCOND:
219 case SP::FBCONDA:
220 case SP::BPICC:
221 case SP::BPICCA:
222 case SP::BPICCNT:
223 case SP::BPICCANT:
224 case SP::BPXCC:
225 case SP::BPXCCA:
226 case SP::BPXCCNT:
227 case SP::BPXCCANT:
228 case SP::BPFCC:
229 case SP::BPFCCA:
230 case SP::BPFCCNT:
231 case SP::BPFCCANT:
232 case SP::FBCOND_V9:
233 case SP::FBCONDA_V9:
234 case SP::BPR:
235 case SP::BPRA:
236 case SP::BPRNT:
237 case SP::BPRANT:
238 return MI.getOperand(0).getMBB();
239 }
240}
241
246 bool AllowModify) const {
249 return false;
250
251 if (!isUnpredicatedTerminator(*I))
252 return false;
253
254
256 unsigned LastOpc = LastInst->getOpcode();
257
258
259 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
262 return false;
263 }
265
267 return false;
268 }
269 return true;
270 }
271
272
274 unsigned SecondLastOpc = SecondLastInst->getOpcode();
275
276
277
281 LastInst = SecondLastInst;
283 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
284
286 return false;
287 } else {
288 SecondLastInst = &*I;
289 SecondLastOpc = SecondLastInst->getOpcode();
290 }
291 }
292 }
293
294
295 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
296 return true;
297
298
302 return false;
303 }
304
305
306
309 return false;
310 }
311
312
313
315 I = LastInst;
316 if (AllowModify)
317 I->eraseFromParent();
318 return true;
319 }
320
321
322 return true;
323}
324
330 int *BytesAdded) const {
331 assert(TBB && "insertBranch must not be told to insert a fallthrough");
333 "Sparc branch conditions should have at most three components!");
334
335 if (Cond.empty()) {
336 assert(!FBB && "Unconditional branch with multiple successors!");
338 if (BytesAdded)
339 *BytesAdded = 8;
340 return 1;
341 }
342
343
344 unsigned Opc = Cond[0].getImm();
345 unsigned CC = Cond[1].getImm();
349 } else {
351 }
352
353 if (!FBB) {
354 if (BytesAdded)
355 *BytesAdded = 8;
356 return 1;
357 }
358
360 if (BytesAdded)
361 *BytesAdded = 16;
362 return 2;
363}
364
366 int *BytesRemoved) const {
368 unsigned Count = 0;
369 int Removed = 0;
371 --I;
372
373 if (I->isDebugInstr())
374 continue;
375
378 break;
379
381 I->eraseFromParent();
383 ++Count;
384 }
385
386 if (BytesRemoved)
387 *BytesRemoved = Removed;
388 return Count;
389}
390
396 return false;
397}
398
400 int64_t Offset) const {
401 assert((Offset & 0b11) == 0 && "Malformed branch offset");
402 switch (BranchOpc) {
403 case SP::BA:
404 case SP::BCOND:
405 case SP::BCONDA:
406 case SP::FBCOND:
407 case SP::FBCONDA:
409
410 case SP::BPICC:
411 case SP::BPICCA:
412 case SP::BPICCNT:
413 case SP::BPICCANT:
414 case SP::BPXCC:
415 case SP::BPXCCA:
416 case SP::BPXCCNT:
417 case SP::BPXCCANT:
418 case SP::BPFCC:
419 case SP::BPFCCA:
420 case SP::BPFCCNT:
421 case SP::BPFCCANT:
422 case SP::FBCOND_V9:
423 case SP::FBCONDA_V9:
425
426 case SP::BPR:
427 case SP::BPRA:
428 case SP::BPRNT:
429 case SP::BPRANT:
431 }
432
434}
435
440 bool RenamableDest, bool RenamableSrc) const {
441 unsigned numSubRegs = 0;
442 unsigned movOpc = 0;
443 const unsigned *subRegIdx = nullptr;
444 bool ExtraG0 = false;
445
446 const unsigned DW_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };
447 const unsigned DFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };
448 const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 };
449 const unsigned QFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd,
450 SP::sub_odd64_then_sub_even,
451 SP::sub_odd64_then_sub_odd };
452
453 if (SP::IntRegsRegClass.contains(DestReg, SrcReg))
456 else if (SP::IntPairRegClass.contains(DestReg, SrcReg)) {
457 subRegIdx = DW_SubRegsIdx;
458 numSubRegs = 2;
459 movOpc = SP::ORrr;
460 ExtraG0 = true;
461 } else if (SP::FPRegsRegClass.contains(DestReg, SrcReg))
464 else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) {
465 if (Subtarget.isV9()) {
468 } else {
469
470 subRegIdx = DFP_FP_SubRegsIdx;
471 numSubRegs = 2;
472 movOpc = SP::FMOVS;
473 }
474 } else if (SP::QFPRegsRegClass.contains(DestReg, SrcReg)) {
475 if (Subtarget.isV9()) {
476 if (Subtarget.hasHardQuad()) {
479 } else {
480
481 subRegIdx = QFP_DFP_SubRegsIdx;
482 numSubRegs = 2;
483 movOpc = SP::FMOVD;
484 }
485 } else {
486
487 subRegIdx = QFP_FP_SubRegsIdx;
488 numSubRegs = 4;
489 movOpc = SP::FMOVS;
490 }
491 } else if (SP::ASRRegsRegClass.contains(DestReg) &&
492 SP::IntRegsRegClass.contains(SrcReg)) {
496 } else if (SP::IntRegsRegClass.contains(DestReg) &&
497 SP::ASRRegsRegClass.contains(SrcReg)) {
500 } else
502
503 if (numSubRegs == 0 || subRegIdx == nullptr || movOpc == 0)
504 return;
505
508
509 for (unsigned i = 0; i != numSubRegs; ++i) {
510 Register Dst = TRI->getSubReg(DestReg, subRegIdx[i]);
511 Register Src = TRI->getSubReg(SrcReg, subRegIdx[i]);
512 assert(Dst && Src && "Bad sub-register");
513
515 if (ExtraG0)
519 }
520
522 if (KillSrc)
524}
525
528 Register SrcReg, bool isKill, int FI,
533 if (I != MBB.end()) DL = I->getDebugLoc();
534
540
541
542 if (RC == &SP::I64RegsRegClass)
545 else if (RC == &SP::IntRegsRegClass)
548 else if (RC == &SP::IntPairRegClass)
551 else if (RC == &SP::FPRegsRegClass)
554 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
557 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
558
559
562 else
564}
565
573 if (I != MBB.end()) DL = I->getDebugLoc();
574
580
581 if (RC == &SP::I64RegsRegClass)
584 else if (RC == &SP::IntRegsRegClass)
587 else if (RC == &SP::IntPairRegClass)
590 else if (RC == &SP::FPRegsRegClass)
593 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
596 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
597
598
601 else
602 llvm_unreachable("Can't load this register from stack slot");
603}
604
608 if (GlobalBaseReg)
609 return GlobalBaseReg;
610
611
615
617 Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
619
621
622 BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg);
624 return GlobalBaseReg;
625}
626
628 unsigned Opcode = MI.getOpcode();
629
630 if (MI.isInlineAsm()) {
632 const char *AsmStr = MI.getOperand(0).getSymbolName();
634 }
635
636
637
638
639 if (MI.hasDelaySlot())
640 return get(Opcode).getSize() * 2;
641 return get(Opcode).getSize();
642}
643
645 switch (MI.getOpcode()) {
646 case TargetOpcode::LOAD_STACK_GUARD: {
648 "Only Linux target is expected to contain LOAD_STACK_GUARD");
649
650 const int64_t Offset = Subtarget.is64Bit() ? 0x28 : 0x14;
651 MI.setDesc(get(Subtarget.is64Bit() ? SP::LDXri : SP::LDri));
655 return true;
656 }
657 }
658 return false;
659}
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
unsigned const TargetRegisterInfo * TRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallVector class.
static bool isFCondBranchOpcode(int Opc)
static bool isRegCondBranchOpcode(int Opc)
static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
static cl::opt< unsigned > BPrDisplacementBits("sparc-bpr-offset-bits", cl::Hidden, cl::init(16), cl::desc("Restrict range of BPr instructions (DEBUG)"))
static bool isI32CondBranchOpcode(int Opc)
static cl::opt< unsigned > BPccDisplacementBits("sparc-bpcc-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of BPcc/FBPfcc instructions (DEBUG)"))
static bool isI64CondBranchOpcode(int Opc)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Wrapper class representing physical registers. Should be passed by value.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
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 & 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.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineBasicBlock * getMBB() const
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Wrapper class representing virtual and physical registers.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
isStoreToStackSlot - If the specified machine instruction is a direct store to a stack slot,...
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t Offset) const override
Determine if the branch target is in range.
SparcInstrInfo(SparcSubtarget &ST)
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Register getGlobalBaseReg(MachineFunction *MF) const
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
isLoadFromStackSlot - If the specified machine instruction is a direct load from a stack slot,...
const SparcRegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
bool expandPostRAPseudo(MachineInstr &MI) const override
Register getGlobalBaseReg() const
void setGlobalBaseReg(Register Reg)
bool isTargetLinux() const
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
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.
static bool isIndirectBranchOpcode(int Opc)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
unsigned getKillRegState(bool B)
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
static bool isUncondBranchOpcode(int Opc)
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.