diff options
Diffstat (limited to 'lib/Target/RISCV/RISCVInstrInfo.cpp')
-rw-r--r-- | lib/Target/RISCV/RISCVInstrInfo.cpp | 118 |
1 files changed, 97 insertions, 21 deletions
diff --git a/lib/Target/RISCV/RISCVInstrInfo.cpp b/lib/Target/RISCV/RISCVInstrInfo.cpp index 99c8d2ef73de..084839299530 100644 --- a/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -14,6 +14,7 @@ #include "RISCV.h" #include "RISCVSubtarget.h" #include "RISCVTargetMachine.h" +#include "Utils/RISCVMatInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -28,8 +29,9 @@ using namespace llvm; -RISCVInstrInfo::RISCVInstrInfo() - : RISCVGenInstrInfo(RISCV::ADJCALLSTACKDOWN, RISCV::ADJCALLSTACKUP) {} +RISCVInstrInfo::RISCVInstrInfo(RISCVSubtarget &STI) + : RISCVGenInstrInfo(RISCV::ADJCALLSTACKDOWN, RISCV::ADJCALLSTACKUP), + STI(STI) {} unsigned RISCVInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const { @@ -156,24 +158,43 @@ void RISCVInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, BuildMI(MBB, I, DL, get(Opcode), DstReg).addFrameIndex(FI).addImm(0); } -void RISCVInstrInfo::movImm32(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, unsigned DstReg, uint64_t Val, - MachineInstr::MIFlag Flag) const { - assert(isInt<32>(Val) && "Can only materialize 32-bit constants"); - - // TODO: If the value can be materialized using only one instruction, only - // insert a single instruction. - - uint64_t Hi20 = ((Val + 0x800) >> 12) & 0xfffff; - uint64_t Lo12 = SignExtend64<12>(Val); - BuildMI(MBB, MBBI, DL, get(RISCV::LUI), DstReg) - .addImm(Hi20) - .setMIFlag(Flag); - BuildMI(MBB, MBBI, DL, get(RISCV::ADDI), DstReg) - .addReg(DstReg, RegState::Kill) - .addImm(Lo12) - .setMIFlag(Flag); +void RISCVInstrInfo::movImm(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, Register DstReg, uint64_t Val, + MachineInstr::MIFlag Flag) const { + MachineFunction *MF = MBB.getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + bool IsRV64 = MF->getSubtarget<RISCVSubtarget>().is64Bit(); + Register SrcReg = RISCV::X0; + Register Result = MRI.createVirtualRegister(&RISCV::GPRRegClass); + unsigned Num = 0; + + if (!IsRV64 && !isInt<32>(Val)) + report_fatal_error("Should only materialize 32-bit constants for RV32"); + + RISCVMatInt::InstSeq Seq; + RISCVMatInt::generateInstSeq(Val, IsRV64, Seq); + assert(Seq.size() > 0); + + for (RISCVMatInt::Inst &Inst : Seq) { + // Write the final result to DstReg if it's the last instruction in the Seq. + // Otherwise, write the result to the temp register. + if (++Num == Seq.size()) + Result = DstReg; + + if (Inst.Opc == RISCV::LUI) { + BuildMI(MBB, MBBI, DL, get(RISCV::LUI), Result) + .addImm(Inst.Imm) + .setMIFlag(Flag); + } else { + BuildMI(MBB, MBBI, DL, get(Inst.Opc), Result) + .addReg(SrcReg, RegState::Kill) + .addImm(Inst.Imm) + .setMIFlag(Flag); + } + // Only the first instruction has X0 as its source. + SrcReg = Result; + } } // The contents of values added to Cond are not examined outside of @@ -372,7 +393,7 @@ unsigned RISCVInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB, // FIXME: A virtual register must be used initially, as the register // scavenger won't work with empty blocks (SIInstrInfo::insertIndirectBranch // uses the same workaround). - unsigned ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); + Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); auto II = MBB.end(); MachineInstr &LuiMI = *BuildMI(MBB, II, DL, get(RISCV::LUI), ScratchReg) @@ -466,3 +487,58 @@ bool RISCVInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const { } return MI.isAsCheapAsAMove(); } + +bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI, + StringRef &ErrInfo) const { + const MCInstrInfo *MCII = STI.getInstrInfo(); + MCInstrDesc const &Desc = MCII->get(MI.getOpcode()); + + for (auto &OI : enumerate(Desc.operands())) { + unsigned OpType = OI.value().OperandType; + if (OpType >= RISCVOp::OPERAND_FIRST_RISCV_IMM && + OpType <= RISCVOp::OPERAND_LAST_RISCV_IMM) { + const MachineOperand &MO = MI.getOperand(OI.index()); + if (MO.isImm()) { + int64_t Imm = MO.getImm(); + bool Ok; + switch (OpType) { + default: + llvm_unreachable("Unexpected operand type"); + case RISCVOp::OPERAND_UIMM4: + Ok = isUInt<4>(Imm); + break; + case RISCVOp::OPERAND_UIMM5: + Ok = isUInt<5>(Imm); + break; + case RISCVOp::OPERAND_UIMM12: + Ok = isUInt<12>(Imm); + break; + case RISCVOp::OPERAND_SIMM12: + Ok = isInt<12>(Imm); + break; + case RISCVOp::OPERAND_SIMM13_LSB0: + Ok = isShiftedInt<12, 1>(Imm); + break; + case RISCVOp::OPERAND_UIMM20: + Ok = isUInt<20>(Imm); + break; + case RISCVOp::OPERAND_SIMM21_LSB0: + Ok = isShiftedInt<20, 1>(Imm); + break; + case RISCVOp::OPERAND_UIMMLOG2XLEN: + if (STI.getTargetTriple().isArch64Bit()) + Ok = isUInt<6>(Imm); + else + Ok = isUInt<5>(Imm); + break; + } + if (!Ok) { + ErrInfo = "Invalid immediate"; + return false; + } + } + } + } + + return true; +} |