aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/RISCV/RISCVInstrInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/RISCV/RISCVInstrInfo.cpp')
-rw-r--r--lib/Target/RISCV/RISCVInstrInfo.cpp118
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;
+}