| //===-- CSKYInstrInfo.h - CSKY Instruction Information --------*- C++ -*---===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains the CSKY implementation of the TargetInstrInfo class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "CSKYInstrInfo.h" |
| #include "CSKYConstantPoolValue.h" |
| #include "CSKYMachineFunctionInfo.h" |
| #include "CSKYTargetMachine.h" |
| #include "llvm/MC/MCContext.h" |
| |
| #define DEBUG_TYPE "csky-instr-info" |
| |
| using namespace llvm; |
| |
| #define GET_INSTRINFO_CTOR_DTOR |
| #include "CSKYGenInstrInfo.inc" |
| |
| CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI) |
| : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) { |
| v2sf = STI.hasFPUv2SingleFloat(); |
| v2df = STI.hasFPUv2DoubleFloat(); |
| v3sf = STI.hasFPUv3SingleFloat(); |
| v3df = STI.hasFPUv3DoubleFloat(); |
| } |
| |
| static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target, |
| SmallVectorImpl<MachineOperand> &Cond) { |
| // Block ends with fall-through condbranch. |
| assert(LastInst.getDesc().isConditionalBranch() && |
| "Unknown conditional branch"); |
| Target = LastInst.getOperand(1).getMBB(); |
| Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode())); |
| Cond.push_back(LastInst.getOperand(0)); |
| } |
| |
| bool CSKYInstrInfo::analyzeBranch(MachineBasicBlock &MBB, |
| MachineBasicBlock *&TBB, |
| MachineBasicBlock *&FBB, |
| SmallVectorImpl<MachineOperand> &Cond, |
| bool AllowModify) const { |
| TBB = FBB = nullptr; |
| Cond.clear(); |
| |
| // If the block has no terminators, it just falls into the block after it. |
| MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); |
| if (I == MBB.end() || !isUnpredicatedTerminator(*I)) |
| return false; |
| |
| // Count the number of terminators and find the first unconditional or |
| // indirect branch. |
| MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end(); |
| int NumTerminators = 0; |
| for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J); |
| J++) { |
| NumTerminators++; |
| if (J->getDesc().isUnconditionalBranch() || |
| J->getDesc().isIndirectBranch()) { |
| FirstUncondOrIndirectBr = J.getReverse(); |
| } |
| } |
| |
| // If AllowModify is true, we can erase any terminators after |
| // FirstUncondOrIndirectBR. |
| if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) { |
| while (std::next(FirstUncondOrIndirectBr) != MBB.end()) { |
| std::next(FirstUncondOrIndirectBr)->eraseFromParent(); |
| NumTerminators--; |
| } |
| I = FirstUncondOrIndirectBr; |
| } |
| |
| // We can't handle blocks that end in an indirect branch. |
| if (I->getDesc().isIndirectBranch()) |
| return true; |
| |
| // We can't handle blocks with more than 2 terminators. |
| if (NumTerminators > 2) |
| return true; |
| |
| // Handle a single unconditional branch. |
| if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) { |
| TBB = getBranchDestBlock(*I); |
| return false; |
| } |
| |
| // Handle a single conditional branch. |
| if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) { |
| parseCondBranch(*I, TBB, Cond); |
| return false; |
| } |
| |
| // Handle a conditional branch followed by an unconditional branch. |
| if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() && |
| I->getDesc().isUnconditionalBranch()) { |
| parseCondBranch(*std::prev(I), TBB, Cond); |
| FBB = getBranchDestBlock(*I); |
| return false; |
| } |
| |
| // Otherwise, we can't handle this. |
| return true; |
| } |
| |
| unsigned CSKYInstrInfo::removeBranch(MachineBasicBlock &MBB, |
| int *BytesRemoved) const { |
| if (BytesRemoved) |
| *BytesRemoved = 0; |
| MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); |
| if (I == MBB.end()) |
| return 0; |
| |
| if (!I->getDesc().isUnconditionalBranch() && |
| !I->getDesc().isConditionalBranch()) |
| return 0; |
| |
| // Remove the branch. |
| if (BytesRemoved) |
| *BytesRemoved += getInstSizeInBytes(*I); |
| I->eraseFromParent(); |
| |
| I = MBB.end(); |
| |
| if (I == MBB.begin()) |
| return 1; |
| --I; |
| if (!I->getDesc().isConditionalBranch()) |
| return 1; |
| |
| // Remove the branch. |
| if (BytesRemoved) |
| *BytesRemoved += getInstSizeInBytes(*I); |
| I->eraseFromParent(); |
| return 2; |
| } |
| |
| MachineBasicBlock * |
| CSKYInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { |
| assert(MI.getDesc().isBranch() && "Unexpected opcode!"); |
| // The branch target is always the last operand. |
| int NumOp = MI.getNumExplicitOperands(); |
| assert(MI.getOperand(NumOp - 1).isMBB() && "Expected MBB!"); |
| return MI.getOperand(NumOp - 1).getMBB(); |
| } |
| |
| unsigned CSKYInstrInfo::insertBranch( |
| MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, |
| ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const { |
| if (BytesAdded) |
| *BytesAdded = 0; |
| |
| // Shouldn't be a fall through. |
| assert(TBB && "insertBranch must not be told to insert a fallthrough"); |
| assert((Cond.size() == 2 || Cond.size() == 0) && |
| "CSKY branch conditions have two components!"); |
| |
| // Unconditional branch. |
| if (Cond.empty()) { |
| MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(TBB); |
| if (BytesAdded) |
| *BytesAdded += getInstSizeInBytes(MI); |
| return 1; |
| } |
| |
| // Either a one or two-way conditional branch. |
| unsigned Opc = Cond[0].getImm(); |
| MachineInstr &CondMI = *BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).addMBB(TBB); |
| if (BytesAdded) |
| *BytesAdded += getInstSizeInBytes(CondMI); |
| |
| // One-way conditional branch. |
| if (!FBB) |
| return 1; |
| |
| // Two-way conditional branch. |
| MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(FBB); |
| if (BytesAdded) |
| *BytesAdded += getInstSizeInBytes(MI); |
| return 2; |
| } |
| |
| static unsigned getOppositeBranchOpc(unsigned Opcode) { |
| switch (Opcode) { |
| default: |
| llvm_unreachable("Unknown conditional branch!"); |
| case CSKY::BT32: |
| return CSKY::BF32; |
| case CSKY::BT16: |
| return CSKY::BF16; |
| case CSKY::BF32: |
| return CSKY::BT32; |
| case CSKY::BF16: |
| return CSKY::BT16; |
| case CSKY::BHZ32: |
| return CSKY::BLSZ32; |
| case CSKY::BHSZ32: |
| return CSKY::BLZ32; |
| case CSKY::BLZ32: |
| return CSKY::BHSZ32; |
| case CSKY::BLSZ32: |
| return CSKY::BHZ32; |
| case CSKY::BNEZ32: |
| return CSKY::BEZ32; |
| case CSKY::BEZ32: |
| return CSKY::BNEZ32; |
| } |
| } |
| |
| bool CSKYInstrInfo::reverseBranchCondition( |
| SmallVectorImpl<MachineOperand> &Cond) const { |
| assert((Cond.size() == 2) && "Invalid branch condition!"); |
| Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); |
| return false; |
| } |
| |
| Register CSKYInstrInfo::movImm(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MBBI, |
| const DebugLoc &DL, int64_t Val, |
| MachineInstr::MIFlag Flag) const { |
| assert(isUInt<32>(Val) && "should be uint32"); |
| |
| MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); |
| |
| Register DstReg; |
| if (STI.hasE2()) { |
| DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass); |
| |
| if (isUInt<16>(Val)) { |
| BuildMI(MBB, MBBI, DL, get(CSKY::MOVI32), DstReg) |
| .addImm(Val & 0xFFFF) |
| .setMIFlags(Flag); |
| } else if (isShiftedUInt<16, 16>(Val)) { |
| BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg) |
| .addImm((Val >> 16) & 0xFFFF) |
| .setMIFlags(Flag); |
| } else { |
| BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg) |
| .addImm((Val >> 16) & 0xFFFF) |
| .setMIFlags(Flag); |
| BuildMI(MBB, MBBI, DL, get(CSKY::ORI32), DstReg) |
| .addReg(DstReg) |
| .addImm(Val & 0xFFFF) |
| .setMIFlags(Flag); |
| } |
| |
| } else { |
| DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass); |
| if (isUInt<8>(Val)) { |
| BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) |
| .addImm(Val & 0xFF) |
| .setMIFlags(Flag); |
| } else if (isUInt<16>(Val)) { |
| BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) |
| .addImm((Val >> 8) & 0xFF) |
| .setMIFlags(Flag); |
| BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) |
| .addReg(DstReg) |
| .addImm(8) |
| .setMIFlags(Flag); |
| if ((Val & 0xFF) != 0) |
| BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) |
| .addReg(DstReg) |
| .addImm(Val & 0xFF) |
| .setMIFlags(Flag); |
| } else if (isUInt<24>(Val)) { |
| BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) |
| .addImm((Val >> 16) & 0xFF) |
| .setMIFlags(Flag); |
| BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) |
| .addReg(DstReg) |
| .addImm(8) |
| .setMIFlags(Flag); |
| if (((Val >> 8) & 0xFF) != 0) |
| BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) |
| .addReg(DstReg) |
| .addImm((Val >> 8) & 0xFF) |
| .setMIFlags(Flag); |
| BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) |
| .addReg(DstReg) |
| .addImm(8) |
| .setMIFlags(Flag); |
| if ((Val & 0xFF) != 0) |
| BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) |
| .addReg(DstReg) |
| .addImm(Val & 0xFF) |
| .setMIFlags(Flag); |
| } else { |
| BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg) |
| .addImm((Val >> 24) & 0xFF) |
| .setMIFlags(Flag); |
| BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) |
| .addReg(DstReg) |
| .addImm(8) |
| .setMIFlags(Flag); |
| if (((Val >> 16) & 0xFF) != 0) |
| BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) |
| .addReg(DstReg) |
| .addImm((Val >> 16) & 0xFF) |
| .setMIFlags(Flag); |
| BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) |
| .addReg(DstReg) |
| .addImm(8) |
| .setMIFlags(Flag); |
| if (((Val >> 8) & 0xFF) != 0) |
| BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) |
| .addReg(DstReg) |
| .addImm((Val >> 8) & 0xFF) |
| .setMIFlags(Flag); |
| BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg) |
| .addReg(DstReg) |
| .addImm(8) |
| .setMIFlags(Flag); |
| if ((Val & 0xFF) != 0) |
| BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg) |
| .addReg(DstReg) |
| .addImm(Val & 0xFF) |
| .setMIFlags(Flag); |
| } |
| } |
| |
| return DstReg; |
| } |
| |
| unsigned CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, |
| int &FrameIndex) const { |
| switch (MI.getOpcode()) { |
| default: |
| return 0; |
| case CSKY::LD16B: |
| case CSKY::LD16H: |
| case CSKY::LD16W: |
| case CSKY::LD32B: |
| case CSKY::LD32BS: |
| case CSKY::LD32H: |
| case CSKY::LD32HS: |
| case CSKY::LD32W: |
| case CSKY::FLD_S: |
| case CSKY::FLD_D: |
| case CSKY::f2FLD_S: |
| case CSKY::f2FLD_D: |
| case CSKY::RESTORE_CARRY: |
| break; |
| } |
| |
| if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && |
| MI.getOperand(2).getImm() == 0) { |
| FrameIndex = MI.getOperand(1).getIndex(); |
| return MI.getOperand(0).getReg(); |
| } |
| |
| return 0; |
| } |
| |
| unsigned CSKYInstrInfo::isStoreToStackSlot(const MachineInstr &MI, |
| int &FrameIndex) const { |
| switch (MI.getOpcode()) { |
| default: |
| return 0; |
| case CSKY::ST16B: |
| case CSKY::ST16H: |
| case CSKY::ST16W: |
| case CSKY::ST32B: |
| case CSKY::ST32H: |
| case CSKY::ST32W: |
| case CSKY::FST_S: |
| case CSKY::FST_D: |
| case CSKY::f2FST_S: |
| case CSKY::f2FST_D: |
| case CSKY::SPILL_CARRY: |
| break; |
| } |
| |
| if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && |
| MI.getOperand(2).getImm() == 0) { |
| FrameIndex = MI.getOperand(1).getIndex(); |
| return MI.getOperand(0).getReg(); |
| } |
| |
| return 0; |
| } |
| |
| void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator I, |
| Register SrcReg, bool IsKill, int FI, |
| const TargetRegisterClass *RC, |
| const TargetRegisterInfo *TRI) const { |
| DebugLoc DL; |
| if (I != MBB.end()) |
| DL = I->getDebugLoc(); |
| |
| MachineFunction &MF = *MBB.getParent(); |
| CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
| MachineFrameInfo &MFI = MF.getFrameInfo(); |
| |
| unsigned Opcode = 0; |
| |
| if (CSKY::GPRRegClass.hasSubClassEq(RC)) { |
| Opcode = CSKY::ST32W; // Optimize for 16bit |
| } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) { |
| Opcode = CSKY::SPILL_CARRY; |
| CFI->setSpillsCR(); |
| } else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC)) |
| Opcode = CSKY::FST_S; |
| else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC)) |
| Opcode = CSKY::FST_D; |
| else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC)) |
| Opcode = CSKY::f2FST_S; |
| else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC)) |
| Opcode = CSKY::f2FST_D; |
| else { |
| llvm_unreachable("Unknown RegisterClass"); |
| } |
| |
| MachineMemOperand *MMO = MF.getMachineMemOperand( |
| MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, |
| MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); |
| |
| BuildMI(MBB, I, DL, get(Opcode)) |
| .addReg(SrcReg, getKillRegState(IsKill)) |
| .addFrameIndex(FI) |
| .addImm(0) |
| .addMemOperand(MMO); |
| } |
| |
| void CSKYInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator I, |
| Register DestReg, int FI, |
| const TargetRegisterClass *RC, |
| const TargetRegisterInfo *TRI) const { |
| DebugLoc DL; |
| if (I != MBB.end()) |
| DL = I->getDebugLoc(); |
| |
| MachineFunction &MF = *MBB.getParent(); |
| CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
| MachineFrameInfo &MFI = MF.getFrameInfo(); |
| |
| unsigned Opcode = 0; |
| |
| if (CSKY::GPRRegClass.hasSubClassEq(RC)) { |
| Opcode = CSKY::LD32W; |
| } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) { |
| Opcode = CSKY::RESTORE_CARRY; |
| CFI->setSpillsCR(); |
| } else if (v2sf && CSKY::sFPR32RegClass.hasSubClassEq(RC)) |
| Opcode = CSKY::FLD_S; |
| else if (v2df && CSKY::sFPR64RegClass.hasSubClassEq(RC)) |
| Opcode = CSKY::FLD_D; |
| else if (v3sf && CSKY::FPR32RegClass.hasSubClassEq(RC)) |
| Opcode = CSKY::f2FLD_S; |
| else if (v3df && CSKY::FPR64RegClass.hasSubClassEq(RC)) |
| Opcode = CSKY::f2FLD_D; |
| else { |
| llvm_unreachable("Unknown RegisterClass"); |
| } |
| |
| MachineMemOperand *MMO = MF.getMachineMemOperand( |
| MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, |
| MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); |
| |
| BuildMI(MBB, I, DL, get(Opcode), DestReg) |
| .addFrameIndex(FI) |
| .addImm(0) |
| .addMemOperand(MMO); |
| } |
| |
| void CSKYInstrInfo::copyPhysReg(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator I, |
| const DebugLoc &DL, MCRegister DestReg, |
| MCRegister SrcReg, bool KillSrc) const { |
| |
| MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); |
| |
| if (CSKY::GPRRegClass.contains(SrcReg) && |
| CSKY::CARRYRegClass.contains(DestReg)) { |
| if (STI.hasE2()) { |
| BuildMI(MBB, I, DL, get(CSKY::BTSTI32), DestReg) |
| .addReg(SrcReg, getKillRegState(KillSrc)) |
| .addImm(0); |
| } else { |
| assert(SrcReg < CSKY::R8); |
| BuildMI(MBB, I, DL, get(CSKY::BTSTI16), DestReg) |
| .addReg(SrcReg, getKillRegState(KillSrc)) |
| .addImm(0); |
| } |
| return; |
| } |
| |
| if (CSKY::CARRYRegClass.contains(SrcReg) && |
| CSKY::GPRRegClass.contains(DestReg)) { |
| |
| if (STI.hasE2()) { |
| BuildMI(MBB, I, DL, get(CSKY::MVC32), DestReg) |
| .addReg(SrcReg, getKillRegState(KillSrc)); |
| } else { |
| assert(DestReg < CSKY::R16); |
| assert(DestReg < CSKY::R8); |
| BuildMI(MBB, I, DL, get(CSKY::MOVI16), DestReg).addImm(0); |
| BuildMI(MBB, I, DL, get(CSKY::ADDC16)) |
| .addReg(DestReg, RegState::Define) |
| .addReg(SrcReg, RegState::Define) |
| .addReg(DestReg, getKillRegState(true)) |
| .addReg(DestReg, getKillRegState(true)) |
| .addReg(SrcReg, getKillRegState(true)); |
| BuildMI(MBB, I, DL, get(CSKY::BTSTI16)) |
| .addReg(SrcReg, RegState::Define | getDeadRegState(KillSrc)) |
| .addReg(DestReg) |
| .addImm(0); |
| } |
| return; |
| } |
| |
| unsigned Opcode = 0; |
| if (CSKY::GPRRegClass.contains(DestReg, SrcReg)) |
| Opcode = CSKY::MOV32; |
| else if (v2sf && CSKY::sFPR32RegClass.contains(DestReg, SrcReg)) |
| Opcode = CSKY::FMOV_S; |
| else if (v3sf && CSKY::FPR32RegClass.contains(DestReg, SrcReg)) |
| Opcode = CSKY::f2FMOV_S; |
| else if (v2df && CSKY::sFPR64RegClass.contains(DestReg, SrcReg)) |
| Opcode = CSKY::FMOV_D; |
| else if (v3df && CSKY::FPR64RegClass.contains(DestReg, SrcReg)) |
| Opcode = CSKY::f2FMOV_D; |
| else if (v2sf && CSKY::sFPR32RegClass.contains(SrcReg) && |
| CSKY::GPRRegClass.contains(DestReg)) |
| Opcode = CSKY::FMFVRL; |
| else if (v3sf && CSKY::FPR32RegClass.contains(SrcReg) && |
| CSKY::GPRRegClass.contains(DestReg)) |
| Opcode = CSKY::f2FMFVRL; |
| else if (v2df && CSKY::sFPR64RegClass.contains(SrcReg) && |
| CSKY::GPRRegClass.contains(DestReg)) |
| Opcode = CSKY::FMFVRL_D; |
| else if (v3df && CSKY::FPR64RegClass.contains(SrcReg) && |
| CSKY::GPRRegClass.contains(DestReg)) |
| Opcode = CSKY::f2FMFVRL_D; |
| else if (v2sf && CSKY::GPRRegClass.contains(SrcReg) && |
| CSKY::sFPR32RegClass.contains(DestReg)) |
| Opcode = CSKY::FMTVRL; |
| else if (v3sf && CSKY::GPRRegClass.contains(SrcReg) && |
| CSKY::FPR32RegClass.contains(DestReg)) |
| Opcode = CSKY::f2FMTVRL; |
| else if (v2df && CSKY::GPRRegClass.contains(SrcReg) && |
| CSKY::sFPR64RegClass.contains(DestReg)) |
| Opcode = CSKY::FMTVRL_D; |
| else if (v3df && CSKY::GPRRegClass.contains(SrcReg) && |
| CSKY::FPR64RegClass.contains(DestReg)) |
| Opcode = CSKY::f2FMTVRL_D; |
| else { |
| LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg); |
| LLVM_DEBUG(I->dump()); |
| llvm_unreachable("Unknown RegisterClass"); |
| } |
| |
| BuildMI(MBB, I, DL, get(Opcode), DestReg) |
| .addReg(SrcReg, getKillRegState(KillSrc)); |
| } |
| |
| Register CSKYInstrInfo::getGlobalBaseReg(MachineFunction &MF) const { |
| CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>(); |
| MachineConstantPool *MCP = MF.getConstantPool(); |
| MachineRegisterInfo &MRI = MF.getRegInfo(); |
| |
| Register GlobalBaseReg = CFI->getGlobalBaseReg(); |
| if (GlobalBaseReg != 0) |
| return GlobalBaseReg; |
| |
| // Insert a pseudo instruction to set the GlobalBaseReg into the first |
| // MBB of the function |
| MachineBasicBlock &FirstMBB = MF.front(); |
| MachineBasicBlock::iterator MBBI = FirstMBB.begin(); |
| DebugLoc DL; |
| |
| CSKYConstantPoolValue *CPV = CSKYConstantPoolSymbol::Create( |
| Type::getInt32Ty(MF.getFunction().getContext()), "_GLOBAL_OFFSET_TABLE_", |
| 0, CSKYCP::ADDR); |
| |
| unsigned CPI = MCP->getConstantPoolIndex(CPV, Align(4)); |
| |
| MachineMemOperand *MO = |
| MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF), |
| MachineMemOperand::MOLoad, 4, Align(4)); |
| BuildMI(FirstMBB, MBBI, DL, get(CSKY::LRW32), CSKY::R28) |
| .addConstantPoolIndex(CPI) |
| .addMemOperand(MO); |
| |
| GlobalBaseReg = MRI.createVirtualRegister(&CSKY::GPRRegClass); |
| BuildMI(FirstMBB, MBBI, DL, get(TargetOpcode::COPY), GlobalBaseReg) |
| .addReg(CSKY::R28); |
| |
| CFI->setGlobalBaseReg(GlobalBaseReg); |
| return GlobalBaseReg; |
| } |
| |
| unsigned CSKYInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { |
| switch (MI.getOpcode()) { |
| default: |
| return MI.getDesc().getSize(); |
| case CSKY::CONSTPOOL_ENTRY: |
| return MI.getOperand(2).getImm(); |
| case CSKY::SPILL_CARRY: |
| case CSKY::RESTORE_CARRY: |
| case CSKY::PseudoTLSLA32: |
| return 8; |
| case TargetOpcode::INLINEASM_BR: |
| case TargetOpcode::INLINEASM: { |
| const MachineFunction *MF = MI.getParent()->getParent(); |
| const char *AsmStr = MI.getOperand(0).getSymbolName(); |
| return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); |
| } |
| } |
| } |