1 //===-- CSKYInstrInfo.h - CSKY Instruction Information --------*- C++ -*---===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains the CSKY implementation of the TargetInstrInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "CSKYInstrInfo.h"
14 #include "CSKYConstantPoolValue.h"
15 #include "CSKYMachineFunctionInfo.h"
16 #include "CSKYTargetMachine.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/MC/MCContext.h"
20 #define DEBUG_TYPE "csky-instr-info"
24 #define GET_INSTRINFO_CTOR_DTOR
25 #include "CSKYGenInstrInfo.inc"
27 CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget
&STI
)
28 : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN
, CSKY::ADJCALLSTACKUP
), STI(STI
) {
29 v2sf
= STI
.hasFPUv2SingleFloat();
30 v2df
= STI
.hasFPUv2DoubleFloat();
31 v3sf
= STI
.hasFPUv3SingleFloat();
32 v3df
= STI
.hasFPUv3DoubleFloat();
35 static void parseCondBranch(MachineInstr
&LastInst
, MachineBasicBlock
*&Target
,
36 SmallVectorImpl
<MachineOperand
> &Cond
) {
37 // Block ends with fall-through condbranch.
38 assert(LastInst
.getDesc().isConditionalBranch() &&
39 "Unknown conditional branch");
40 Target
= LastInst
.getOperand(1).getMBB();
41 Cond
.push_back(MachineOperand::CreateImm(LastInst
.getOpcode()));
42 Cond
.push_back(LastInst
.getOperand(0));
45 bool CSKYInstrInfo::analyzeBranch(MachineBasicBlock
&MBB
,
46 MachineBasicBlock
*&TBB
,
47 MachineBasicBlock
*&FBB
,
48 SmallVectorImpl
<MachineOperand
> &Cond
,
49 bool AllowModify
) const {
53 // If the block has no terminators, it just falls into the block after it.
54 MachineBasicBlock::iterator I
= MBB
.getLastNonDebugInstr();
55 if (I
== MBB
.end() || !isUnpredicatedTerminator(*I
))
58 // Count the number of terminators and find the first unconditional or
60 MachineBasicBlock::iterator FirstUncondOrIndirectBr
= MBB
.end();
61 int NumTerminators
= 0;
62 for (auto J
= I
.getReverse(); J
!= MBB
.rend() && isUnpredicatedTerminator(*J
);
65 if (J
->getDesc().isUnconditionalBranch() ||
66 J
->getDesc().isIndirectBranch()) {
67 FirstUncondOrIndirectBr
= J
.getReverse();
71 // If AllowModify is true, we can erase any terminators after
72 // FirstUncondOrIndirectBR.
73 if (AllowModify
&& FirstUncondOrIndirectBr
!= MBB
.end()) {
74 while (std::next(FirstUncondOrIndirectBr
) != MBB
.end()) {
75 std::next(FirstUncondOrIndirectBr
)->eraseFromParent();
78 I
= FirstUncondOrIndirectBr
;
81 // We can't handle blocks that end in an indirect branch.
82 if (I
->getDesc().isIndirectBranch())
85 // We can't handle blocks with more than 2 terminators.
86 if (NumTerminators
> 2)
89 // Handle a single unconditional branch.
90 if (NumTerminators
== 1 && I
->getDesc().isUnconditionalBranch()) {
91 TBB
= getBranchDestBlock(*I
);
95 // Handle a single conditional branch.
96 if (NumTerminators
== 1 && I
->getDesc().isConditionalBranch()) {
97 parseCondBranch(*I
, TBB
, Cond
);
101 // Handle a conditional branch followed by an unconditional branch.
102 if (NumTerminators
== 2 && std::prev(I
)->getDesc().isConditionalBranch() &&
103 I
->getDesc().isUnconditionalBranch()) {
104 parseCondBranch(*std::prev(I
), TBB
, Cond
);
105 FBB
= getBranchDestBlock(*I
);
109 // Otherwise, we can't handle this.
113 unsigned CSKYInstrInfo::removeBranch(MachineBasicBlock
&MBB
,
114 int *BytesRemoved
) const {
117 MachineBasicBlock::iterator I
= MBB
.getLastNonDebugInstr();
121 if (!I
->getDesc().isUnconditionalBranch() &&
122 !I
->getDesc().isConditionalBranch())
125 // Remove the branch.
127 *BytesRemoved
+= getInstSizeInBytes(*I
);
128 I
->eraseFromParent();
132 if (I
== MBB
.begin())
135 if (!I
->getDesc().isConditionalBranch())
138 // Remove the branch.
140 *BytesRemoved
+= getInstSizeInBytes(*I
);
141 I
->eraseFromParent();
146 CSKYInstrInfo::getBranchDestBlock(const MachineInstr
&MI
) const {
147 assert(MI
.getDesc().isBranch() && "Unexpected opcode!");
148 // The branch target is always the last operand.
149 int NumOp
= MI
.getNumExplicitOperands();
150 assert(MI
.getOperand(NumOp
- 1).isMBB() && "Expected MBB!");
151 return MI
.getOperand(NumOp
- 1).getMBB();
154 unsigned CSKYInstrInfo::insertBranch(
155 MachineBasicBlock
&MBB
, MachineBasicBlock
*TBB
, MachineBasicBlock
*FBB
,
156 ArrayRef
<MachineOperand
> Cond
, const DebugLoc
&DL
, int *BytesAdded
) const {
160 // Shouldn't be a fall through.
161 assert(TBB
&& "insertBranch must not be told to insert a fallthrough");
162 assert((Cond
.size() == 2 || Cond
.size() == 0) &&
163 "CSKY branch conditions have two components!");
165 // Unconditional branch.
167 MachineInstr
&MI
= *BuildMI(&MBB
, DL
, get(CSKY::BR32
)).addMBB(TBB
);
169 *BytesAdded
+= getInstSizeInBytes(MI
);
173 // Either a one or two-way conditional branch.
174 unsigned Opc
= Cond
[0].getImm();
175 MachineInstr
&CondMI
= *BuildMI(&MBB
, DL
, get(Opc
)).add(Cond
[1]).addMBB(TBB
);
177 *BytesAdded
+= getInstSizeInBytes(CondMI
);
179 // One-way conditional branch.
183 // Two-way conditional branch.
184 MachineInstr
&MI
= *BuildMI(&MBB
, DL
, get(CSKY::BR32
)).addMBB(FBB
);
186 *BytesAdded
+= getInstSizeInBytes(MI
);
190 static unsigned getOppositeBranchOpc(unsigned Opcode
) {
193 llvm_unreachable("Unknown conditional branch!");
217 bool CSKYInstrInfo::reverseBranchCondition(
218 SmallVectorImpl
<MachineOperand
> &Cond
) const {
219 assert((Cond
.size() == 2) && "Invalid branch condition!");
220 Cond
[0].setImm(getOppositeBranchOpc(Cond
[0].getImm()));
224 Register
CSKYInstrInfo::movImm(MachineBasicBlock
&MBB
,
225 MachineBasicBlock::iterator MBBI
,
226 const DebugLoc
&DL
, uint64_t Val
,
227 MachineInstr::MIFlag Flag
) const {
229 report_fatal_error("Should only materialize 32-bit constants.");
231 MachineRegisterInfo
&MRI
= MBB
.getParent()->getRegInfo();
235 DstReg
= MRI
.createVirtualRegister(&CSKY::GPRRegClass
);
237 if (isUInt
<16>(Val
)) {
238 BuildMI(MBB
, MBBI
, DL
, get(CSKY::MOVI32
), DstReg
)
239 .addImm(Val
& 0xFFFF)
241 } else if (isShiftedUInt
<16, 16>(Val
)) {
242 BuildMI(MBB
, MBBI
, DL
, get(CSKY::MOVIH32
), DstReg
)
243 .addImm((Val
>> 16) & 0xFFFF)
246 BuildMI(MBB
, MBBI
, DL
, get(CSKY::MOVIH32
), DstReg
)
247 .addImm((Val
>> 16) & 0xFFFF)
249 BuildMI(MBB
, MBBI
, DL
, get(CSKY::ORI32
), DstReg
)
251 .addImm(Val
& 0xFFFF)
256 DstReg
= MRI
.createVirtualRegister(&CSKY::mGPRRegClass
);
257 if (isUInt
<8>(Val
)) {
258 BuildMI(MBB
, MBBI
, DL
, get(CSKY::MOVI16
), DstReg
)
261 } else if (isUInt
<16>(Val
)) {
262 BuildMI(MBB
, MBBI
, DL
, get(CSKY::MOVI16
), DstReg
)
263 .addImm((Val
>> 8) & 0xFF)
265 BuildMI(MBB
, MBBI
, DL
, get(CSKY::LSLI16
), DstReg
)
269 if ((Val
& 0xFF) != 0)
270 BuildMI(MBB
, MBBI
, DL
, get(CSKY::ADDI16
), DstReg
)
274 } else if (isUInt
<24>(Val
)) {
275 BuildMI(MBB
, MBBI
, DL
, get(CSKY::MOVI16
), DstReg
)
276 .addImm((Val
>> 16) & 0xFF)
278 BuildMI(MBB
, MBBI
, DL
, get(CSKY::LSLI16
), DstReg
)
282 if (((Val
>> 8) & 0xFF) != 0)
283 BuildMI(MBB
, MBBI
, DL
, get(CSKY::ADDI16
), DstReg
)
285 .addImm((Val
>> 8) & 0xFF)
287 BuildMI(MBB
, MBBI
, DL
, get(CSKY::LSLI16
), DstReg
)
291 if ((Val
& 0xFF) != 0)
292 BuildMI(MBB
, MBBI
, DL
, get(CSKY::ADDI16
), DstReg
)
297 BuildMI(MBB
, MBBI
, DL
, get(CSKY::MOVI16
), DstReg
)
298 .addImm((Val
>> 24) & 0xFF)
300 BuildMI(MBB
, MBBI
, DL
, get(CSKY::LSLI16
), DstReg
)
304 if (((Val
>> 16) & 0xFF) != 0)
305 BuildMI(MBB
, MBBI
, DL
, get(CSKY::ADDI16
), DstReg
)
307 .addImm((Val
>> 16) & 0xFF)
309 BuildMI(MBB
, MBBI
, DL
, get(CSKY::LSLI16
), DstReg
)
313 if (((Val
>> 8) & 0xFF) != 0)
314 BuildMI(MBB
, MBBI
, DL
, get(CSKY::ADDI16
), DstReg
)
316 .addImm((Val
>> 8) & 0xFF)
318 BuildMI(MBB
, MBBI
, DL
, get(CSKY::LSLI16
), DstReg
)
322 if ((Val
& 0xFF) != 0)
323 BuildMI(MBB
, MBBI
, DL
, get(CSKY::ADDI16
), DstReg
)
333 Register
CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr
&MI
,
334 int &FrameIndex
) const {
335 switch (MI
.getOpcode()) {
350 case CSKY::RESTORE_CARRY
:
354 if (MI
.getOperand(1).isFI() && MI
.getOperand(2).isImm() &&
355 MI
.getOperand(2).getImm() == 0) {
356 FrameIndex
= MI
.getOperand(1).getIndex();
357 return MI
.getOperand(0).getReg();
363 Register
CSKYInstrInfo::isStoreToStackSlot(const MachineInstr
&MI
,
364 int &FrameIndex
) const {
365 switch (MI
.getOpcode()) {
378 case CSKY::SPILL_CARRY
:
382 if (MI
.getOperand(1).isFI() && MI
.getOperand(2).isImm() &&
383 MI
.getOperand(2).getImm() == 0) {
384 FrameIndex
= MI
.getOperand(1).getIndex();
385 return MI
.getOperand(0).getReg();
391 void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock
&MBB
,
392 MachineBasicBlock::iterator I
,
393 Register SrcReg
, bool IsKill
, int FI
,
394 const TargetRegisterClass
*RC
,
395 const TargetRegisterInfo
*TRI
,
397 MachineInstr::MIFlag Flags
) const {
400 DL
= I
->getDebugLoc();
402 MachineFunction
&MF
= *MBB
.getParent();
403 CSKYMachineFunctionInfo
*CFI
= MF
.getInfo
<CSKYMachineFunctionInfo
>();
404 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
408 if (CSKY::GPRRegClass
.hasSubClassEq(RC
)) {
409 Opcode
= CSKY::ST32W
; // Optimize for 16bit
410 } else if (CSKY::CARRYRegClass
.hasSubClassEq(RC
)) {
411 Opcode
= CSKY::SPILL_CARRY
;
413 } else if (v2sf
&& CSKY::sFPR32RegClass
.hasSubClassEq(RC
))
414 Opcode
= CSKY::FST_S
;
415 else if (v2df
&& CSKY::sFPR64RegClass
.hasSubClassEq(RC
))
416 Opcode
= CSKY::FST_D
;
417 else if (v3sf
&& CSKY::FPR32RegClass
.hasSubClassEq(RC
))
418 Opcode
= CSKY::f2FST_S
;
419 else if (v3df
&& CSKY::FPR64RegClass
.hasSubClassEq(RC
))
420 Opcode
= CSKY::f2FST_D
;
422 llvm_unreachable("Unknown RegisterClass");
425 MachineMemOperand
*MMO
= MF
.getMachineMemOperand(
426 MachinePointerInfo::getFixedStack(MF
, FI
), MachineMemOperand::MOStore
,
427 MFI
.getObjectSize(FI
), MFI
.getObjectAlign(FI
));
429 BuildMI(MBB
, I
, DL
, get(Opcode
))
430 .addReg(SrcReg
, getKillRegState(IsKill
))
436 void CSKYInstrInfo::loadRegFromStackSlot(
437 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
, Register DestReg
,
438 int FI
, const TargetRegisterClass
*RC
, const TargetRegisterInfo
*TRI
,
439 Register VReg
, MachineInstr::MIFlag Flags
) const {
442 DL
= I
->getDebugLoc();
444 MachineFunction
&MF
= *MBB
.getParent();
445 CSKYMachineFunctionInfo
*CFI
= MF
.getInfo
<CSKYMachineFunctionInfo
>();
446 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
450 if (CSKY::GPRRegClass
.hasSubClassEq(RC
)) {
451 Opcode
= CSKY::LD32W
;
452 } else if (CSKY::CARRYRegClass
.hasSubClassEq(RC
)) {
453 Opcode
= CSKY::RESTORE_CARRY
;
455 } else if (v2sf
&& CSKY::sFPR32RegClass
.hasSubClassEq(RC
))
456 Opcode
= CSKY::FLD_S
;
457 else if (v2df
&& CSKY::sFPR64RegClass
.hasSubClassEq(RC
))
458 Opcode
= CSKY::FLD_D
;
459 else if (v3sf
&& CSKY::FPR32RegClass
.hasSubClassEq(RC
))
460 Opcode
= CSKY::f2FLD_S
;
461 else if (v3df
&& CSKY::FPR64RegClass
.hasSubClassEq(RC
))
462 Opcode
= CSKY::f2FLD_D
;
464 llvm_unreachable("Unknown RegisterClass");
467 MachineMemOperand
*MMO
= MF
.getMachineMemOperand(
468 MachinePointerInfo::getFixedStack(MF
, FI
), MachineMemOperand::MOLoad
,
469 MFI
.getObjectSize(FI
), MFI
.getObjectAlign(FI
));
471 BuildMI(MBB
, I
, DL
, get(Opcode
), DestReg
)
477 void CSKYInstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
478 MachineBasicBlock::iterator I
,
479 const DebugLoc
&DL
, MCRegister DestReg
,
480 MCRegister SrcReg
, bool KillSrc
,
481 bool RenamableDest
, bool RenamableSrc
) const {
482 if (CSKY::GPRRegClass
.contains(SrcReg
) &&
483 CSKY::CARRYRegClass
.contains(DestReg
)) {
485 BuildMI(MBB
, I
, DL
, get(CSKY::BTSTI32
), DestReg
)
486 .addReg(SrcReg
, getKillRegState(KillSrc
))
489 assert(SrcReg
< CSKY::R8
);
490 BuildMI(MBB
, I
, DL
, get(CSKY::BTSTI16
), DestReg
)
491 .addReg(SrcReg
, getKillRegState(KillSrc
))
497 if (CSKY::CARRYRegClass
.contains(SrcReg
) &&
498 CSKY::GPRRegClass
.contains(DestReg
)) {
501 BuildMI(MBB
, I
, DL
, get(CSKY::MVC32
), DestReg
)
502 .addReg(SrcReg
, getKillRegState(KillSrc
));
504 assert(DestReg
< CSKY::R16
);
505 assert(DestReg
< CSKY::R8
);
506 BuildMI(MBB
, I
, DL
, get(CSKY::MOVI16
), DestReg
).addImm(0);
507 BuildMI(MBB
, I
, DL
, get(CSKY::ADDC16
))
508 .addReg(DestReg
, RegState::Define
)
509 .addReg(SrcReg
, RegState::Define
)
510 .addReg(DestReg
, getKillRegState(true))
511 .addReg(DestReg
, getKillRegState(true))
512 .addReg(SrcReg
, getKillRegState(true));
513 BuildMI(MBB
, I
, DL
, get(CSKY::BTSTI16
))
514 .addReg(SrcReg
, RegState::Define
| getDeadRegState(KillSrc
))
522 if (CSKY::GPRRegClass
.contains(DestReg
, SrcReg
))
523 Opcode
= STI
.hasE2() ? CSKY::MOV32
: CSKY::MOV16
;
524 else if (v2sf
&& CSKY::sFPR32RegClass
.contains(DestReg
, SrcReg
))
525 Opcode
= CSKY::FMOV_S
;
526 else if (v3sf
&& CSKY::FPR32RegClass
.contains(DestReg
, SrcReg
))
527 Opcode
= CSKY::f2FMOV_S
;
528 else if (v2df
&& CSKY::sFPR64RegClass
.contains(DestReg
, SrcReg
))
529 Opcode
= CSKY::FMOV_D
;
530 else if (v3df
&& CSKY::FPR64RegClass
.contains(DestReg
, SrcReg
))
531 Opcode
= CSKY::f2FMOV_D
;
532 else if (v2sf
&& CSKY::sFPR32RegClass
.contains(SrcReg
) &&
533 CSKY::GPRRegClass
.contains(DestReg
))
534 Opcode
= CSKY::FMFVRL
;
535 else if (v3sf
&& CSKY::FPR32RegClass
.contains(SrcReg
) &&
536 CSKY::GPRRegClass
.contains(DestReg
))
537 Opcode
= CSKY::f2FMFVRL
;
538 else if (v2df
&& CSKY::sFPR64RegClass
.contains(SrcReg
) &&
539 CSKY::GPRRegClass
.contains(DestReg
))
540 Opcode
= CSKY::FMFVRL_D
;
541 else if (v3df
&& CSKY::FPR64RegClass
.contains(SrcReg
) &&
542 CSKY::GPRRegClass
.contains(DestReg
))
543 Opcode
= CSKY::f2FMFVRL_D
;
544 else if (v2sf
&& CSKY::GPRRegClass
.contains(SrcReg
) &&
545 CSKY::sFPR32RegClass
.contains(DestReg
))
546 Opcode
= CSKY::FMTVRL
;
547 else if (v3sf
&& CSKY::GPRRegClass
.contains(SrcReg
) &&
548 CSKY::FPR32RegClass
.contains(DestReg
))
549 Opcode
= CSKY::f2FMTVRL
;
550 else if (v2df
&& CSKY::GPRRegClass
.contains(SrcReg
) &&
551 CSKY::sFPR64RegClass
.contains(DestReg
))
552 Opcode
= CSKY::FMTVRL_D
;
553 else if (v3df
&& CSKY::GPRRegClass
.contains(SrcReg
) &&
554 CSKY::FPR64RegClass
.contains(DestReg
))
555 Opcode
= CSKY::f2FMTVRL_D
;
557 LLVM_DEBUG(dbgs() << "src = " << SrcReg
<< ", dst = " << DestReg
);
558 LLVM_DEBUG(I
->dump());
559 llvm_unreachable("Unknown RegisterClass");
562 BuildMI(MBB
, I
, DL
, get(Opcode
), DestReg
)
563 .addReg(SrcReg
, getKillRegState(KillSrc
));
566 Register
CSKYInstrInfo::getGlobalBaseReg(MachineFunction
&MF
) const {
567 CSKYMachineFunctionInfo
*CFI
= MF
.getInfo
<CSKYMachineFunctionInfo
>();
568 MachineConstantPool
*MCP
= MF
.getConstantPool();
569 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
571 Register GlobalBaseReg
= CFI
->getGlobalBaseReg();
572 if (GlobalBaseReg
!= 0)
573 return GlobalBaseReg
;
575 // Insert a pseudo instruction to set the GlobalBaseReg into the first
576 // MBB of the function
577 MachineBasicBlock
&FirstMBB
= MF
.front();
578 MachineBasicBlock::iterator MBBI
= FirstMBB
.begin();
581 CSKYConstantPoolValue
*CPV
= CSKYConstantPoolSymbol::Create(
582 Type::getInt32Ty(MF
.getFunction().getContext()), "_GLOBAL_OFFSET_TABLE_",
585 unsigned CPI
= MCP
->getConstantPoolIndex(CPV
, Align(4));
587 MachineMemOperand
*MO
=
588 MF
.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF
),
589 MachineMemOperand::MOLoad
, 4, Align(4));
590 BuildMI(FirstMBB
, MBBI
, DL
, get(CSKY::LRW32
), CSKY::R28
)
591 .addConstantPoolIndex(CPI
)
594 GlobalBaseReg
= MRI
.createVirtualRegister(&CSKY::GPRRegClass
);
595 BuildMI(FirstMBB
, MBBI
, DL
, get(TargetOpcode::COPY
), GlobalBaseReg
)
598 CFI
->setGlobalBaseReg(GlobalBaseReg
);
599 return GlobalBaseReg
;
602 unsigned CSKYInstrInfo::getInstSizeInBytes(const MachineInstr
&MI
) const {
603 switch (MI
.getOpcode()) {
605 return MI
.getDesc().getSize();
606 case CSKY::CONSTPOOL_ENTRY
:
607 return MI
.getOperand(2).getImm();
608 case CSKY::SPILL_CARRY
:
609 case CSKY::RESTORE_CARRY
:
610 case CSKY::PseudoTLSLA32
:
612 case TargetOpcode::INLINEASM_BR
:
613 case TargetOpcode::INLINEASM
: {
614 const MachineFunction
*MF
= MI
.getParent()->getParent();
615 const char *AsmStr
= MI
.getOperand(0).getSymbolName();
616 return getInlineAsmLength(AsmStr
, *MF
->getTarget().getMCAsmInfo());