[llvm] [RISCV] Make RISCVInstrInfo::verifyInstruction stricter for immediate-only operands (PR #170736)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 4 12:26:11 PST 2025
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/170736
Most of the immediate operands can only be an immediate, but we were allowing any non-register operand.
Split the immediate-only from the immediate or non-register operands. The non-register cases could be made even stricter, but I'll leave that as a TODO.
>From fd397255ecef4da3c8452b70f5560dcd045aaf0b Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Thu, 4 Dec 2025 11:41:31 -0800
Subject: [PATCH] [RISCV] Make RISCVInstrInfo::verifyInstruction stricter for
immediate-only operands
Most of the immediate operands can only be an immediate, but we were
allowing any non-register operand.
Split the immediate-only from the immediate or non-register operands.
The non-register cases could be made even stricter, but I'll leave that
as a TODO.
---
.../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h | 12 +-
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 392 ++++++++++--------
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 3 +
3 files changed, 221 insertions(+), 186 deletions(-)
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index d8dcd963050b5..dbf5cfe6ef463 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -393,7 +393,6 @@ enum OperandType : unsigned {
OPERAND_UIMM14_LSB00,
OPERAND_UIMM16,
OPERAND_UIMM16_NONZERO,
- OPERAND_UIMM20,
OPERAND_UIMMLOG2XLEN,
OPERAND_UIMMLOG2XLEN_NONZERO,
OPERAND_UIMM32,
@@ -412,13 +411,11 @@ enum OperandType : unsigned {
OPERAND_SIMM10_LSB0000_NONZERO,
OPERAND_SIMM10_UNSIGNED,
OPERAND_SIMM11,
- OPERAND_SIMM12,
OPERAND_SIMM12_LSB00000,
OPERAND_SIMM16,
OPERAND_SIMM16_NONZERO,
OPERAND_SIMM20_LI,
OPERAND_SIMM26,
- OPERAND_BARE_SIMM32,
OPERAND_CLUI_IMM,
OPERAND_VTYPEI10,
OPERAND_VTYPEI11,
@@ -447,6 +444,15 @@ enum OperandType : unsigned {
// Vtype operand for XSfmm extension.
OPERAND_XSFMM_VTYPE,
OPERAND_LAST_RISCV_IMM = OPERAND_XSFMM_VTYPE,
+
+ OPERAND_UIMM20_LUI,
+ OPERAND_UIMM20_AUIPC,
+
+ // Simm12 or constant pool, global, basicblock, etc.
+ OPERAND_SIMM12_LO,
+
+ OPERAND_BARE_SIMM32,
+
// Operand is either a register or uimm5, this is used by V extension pseudo
// instructions to represent a value that be passed as AVL to either vsetvli
// or vsetivli.
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 2bd63e75d060b..ee327f3d61a62 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -2850,22 +2850,21 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
MCInstrDesc const &Desc = MI.getDesc();
for (const auto &[Index, Operand] : enumerate(Desc.operands())) {
+ const MachineOperand &MO = MI.getOperand(Index);
unsigned OpType = Operand.OperandType;
if (OpType >= RISCVOp::OPERAND_FIRST_RISCV_IMM &&
OpType <= RISCVOp::OPERAND_LAST_RISCV_IMM) {
- const MachineOperand &MO = MI.getOperand(Index);
- if (MO.isReg()) {
- ErrInfo = "Expected a non-register operand.";
+ if (!MO.isImm()) {
+ ErrInfo = "Expected an immediate operand.";
return false;
}
- if (MO.isImm()) {
- int64_t Imm = MO.getImm();
- bool Ok;
- switch (OpType) {
- default:
- llvm_unreachable("Unexpected operand type");
+ int64_t Imm = MO.getImm();
+ bool Ok;
+ switch (OpType) {
+ default:
+ llvm_unreachable("Unexpected operand type");
- // clang-format off
+ // clang-format off
#define CASE_OPERAND_UIMM(NUM) \
case RISCVOp::OPERAND_UIMM##NUM: \
Ok = isUInt<NUM>(Imm); \
@@ -2874,181 +2873,208 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
case RISCVOp::OPERAND_SIMM##NUM: \
Ok = isInt<NUM>(Imm); \
break;
- CASE_OPERAND_UIMM(1)
- CASE_OPERAND_UIMM(2)
- CASE_OPERAND_UIMM(3)
- CASE_OPERAND_UIMM(4)
- CASE_OPERAND_UIMM(5)
- CASE_OPERAND_UIMM(6)
- CASE_OPERAND_UIMM(7)
- CASE_OPERAND_UIMM(8)
- CASE_OPERAND_UIMM(9)
- CASE_OPERAND_UIMM(10)
- CASE_OPERAND_UIMM(12)
- CASE_OPERAND_UIMM(16)
- CASE_OPERAND_UIMM(20)
- CASE_OPERAND_UIMM(32)
- CASE_OPERAND_UIMM(48)
- CASE_OPERAND_UIMM(64)
- // clang-format on
- case RISCVOp::OPERAND_UIMM2_LSB0:
- Ok = isShiftedUInt<1, 1>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM5_LSB0:
- Ok = isShiftedUInt<4, 1>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM5_NONZERO:
- Ok = isUInt<5>(Imm) && (Imm != 0);
- break;
- case RISCVOp::OPERAND_UIMM5_GT3:
- Ok = isUInt<5>(Imm) && (Imm > 3);
- break;
- case RISCVOp::OPERAND_UIMM5_PLUS1:
- Ok = Imm >= 1 && Imm <= 32;
- break;
- case RISCVOp::OPERAND_UIMM6_LSB0:
- Ok = isShiftedUInt<5, 1>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM7_LSB00:
- Ok = isShiftedUInt<5, 2>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM7_LSB000:
- Ok = isShiftedUInt<4, 3>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM8_LSB00:
- Ok = isShiftedUInt<6, 2>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM8_LSB000:
- Ok = isShiftedUInt<5, 3>(Imm);
- break;
- case RISCVOp::OPERAND_UIMM8_GE32:
- Ok = isUInt<8>(Imm) && Imm >= 32;
- break;
- case RISCVOp::OPERAND_UIMM9_LSB000:
- Ok = isShiftedUInt<6, 3>(Imm);
- break;
- case RISCVOp::OPERAND_SIMM8_UNSIGNED:
- Ok = isInt<8>(Imm);
- break;
- case RISCVOp::OPERAND_SIMM10_LSB0000_NONZERO:
- Ok = isShiftedInt<6, 4>(Imm) && (Imm != 0);
- break;
- case RISCVOp::OPERAND_UIMM10_LSB00_NONZERO:
- Ok = isShiftedUInt<8, 2>(Imm) && (Imm != 0);
- break;
- case RISCVOp::OPERAND_UIMM16_NONZERO:
- Ok = isUInt<16>(Imm) && (Imm != 0);
- break;
- case RISCVOp::OPERAND_THREE:
- Ok = Imm == 3;
- break;
- case RISCVOp::OPERAND_FOUR:
- Ok = Imm == 4;
- break;
- case RISCVOp::OPERAND_IMM5_ZIBI:
- Ok = (isUInt<5>(Imm) && Imm != 0) || Imm == -1;
- break;
- // clang-format off
- CASE_OPERAND_SIMM(5)
- CASE_OPERAND_SIMM(6)
- CASE_OPERAND_SIMM(10)
- CASE_OPERAND_SIMM(11)
- CASE_OPERAND_SIMM(12)
- CASE_OPERAND_SIMM(26)
+ CASE_OPERAND_UIMM(1)
+ CASE_OPERAND_UIMM(2)
+ CASE_OPERAND_UIMM(3)
+ CASE_OPERAND_UIMM(4)
+ CASE_OPERAND_UIMM(5)
+ CASE_OPERAND_UIMM(6)
+ CASE_OPERAND_UIMM(7)
+ CASE_OPERAND_UIMM(8)
+ CASE_OPERAND_UIMM(9)
+ CASE_OPERAND_UIMM(10)
+ CASE_OPERAND_UIMM(12)
+ CASE_OPERAND_UIMM(16)
+ CASE_OPERAND_UIMM(32)
+ CASE_OPERAND_UIMM(48)
+ CASE_OPERAND_UIMM(64)
// clang-format on
- case RISCVOp::OPERAND_SIMM5_PLUS1:
- Ok = Imm >= -15 && Imm <= 16;
- break;
- case RISCVOp::OPERAND_SIMM5_NONZERO:
- Ok = isInt<5>(Imm) && (Imm != 0);
- break;
- case RISCVOp::OPERAND_SIMM6_NONZERO:
- Ok = Imm != 0 && isInt<6>(Imm);
- break;
- case RISCVOp::OPERAND_VTYPEI10:
- Ok = isUInt<10>(Imm);
- break;
- case RISCVOp::OPERAND_VTYPEI11:
- Ok = isUInt<11>(Imm);
- break;
- case RISCVOp::OPERAND_SIMM12_LSB00000:
- Ok = isShiftedInt<7, 5>(Imm);
- break;
- case RISCVOp::OPERAND_SIMM16_NONZERO:
- Ok = isInt<16>(Imm) && (Imm != 0);
- break;
- case RISCVOp::OPERAND_SIMM20_LI:
- Ok = isInt<20>(Imm);
- break;
- case RISCVOp::OPERAND_BARE_SIMM32:
- Ok = isInt<32>(Imm);
- break;
- case RISCVOp::OPERAND_UIMMLOG2XLEN:
- Ok = STI.is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
- break;
- case RISCVOp::OPERAND_UIMMLOG2XLEN_NONZERO:
- Ok = STI.is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
- Ok = Ok && Imm != 0;
- break;
- case RISCVOp::OPERAND_CLUI_IMM:
- Ok = (isUInt<5>(Imm) && Imm != 0) ||
- (Imm >= 0xfffe0 && Imm <= 0xfffff);
- break;
- case RISCVOp::OPERAND_RVKRNUM:
- Ok = Imm >= 0 && Imm <= 10;
- break;
- case RISCVOp::OPERAND_RVKRNUM_0_7:
- Ok = Imm >= 0 && Imm <= 7;
- break;
- case RISCVOp::OPERAND_RVKRNUM_1_10:
- Ok = Imm >= 1 && Imm <= 10;
- break;
- case RISCVOp::OPERAND_RVKRNUM_2_14:
- Ok = Imm >= 2 && Imm <= 14;
- break;
- case RISCVOp::OPERAND_RLIST:
- Ok = Imm >= RISCVZC::RA && Imm <= RISCVZC::RA_S0_S11;
- break;
- case RISCVOp::OPERAND_RLIST_S0:
- Ok = Imm >= RISCVZC::RA_S0 && Imm <= RISCVZC::RA_S0_S11;
- break;
- case RISCVOp::OPERAND_STACKADJ:
- Ok = Imm >= 0 && Imm <= 48 && Imm % 16 == 0;
- break;
- case RISCVOp::OPERAND_FRMARG:
+ case RISCVOp::OPERAND_UIMM2_LSB0:
+ Ok = isShiftedUInt<1, 1>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMM5_LSB0:
+ Ok = isShiftedUInt<4, 1>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMM5_NONZERO:
+ Ok = isUInt<5>(Imm) && (Imm != 0);
+ break;
+ case RISCVOp::OPERAND_UIMM5_GT3:
+ Ok = isUInt<5>(Imm) && (Imm > 3);
+ break;
+ case RISCVOp::OPERAND_UIMM5_PLUS1:
+ Ok = Imm >= 1 && Imm <= 32;
+ break;
+ case RISCVOp::OPERAND_UIMM6_LSB0:
+ Ok = isShiftedUInt<5, 1>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMM7_LSB00:
+ Ok = isShiftedUInt<5, 2>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMM7_LSB000:
+ Ok = isShiftedUInt<4, 3>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMM8_LSB00:
+ Ok = isShiftedUInt<6, 2>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMM8_LSB000:
+ Ok = isShiftedUInt<5, 3>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMM8_GE32:
+ Ok = isUInt<8>(Imm) && Imm >= 32;
+ break;
+ case RISCVOp::OPERAND_UIMM9_LSB000:
+ Ok = isShiftedUInt<6, 3>(Imm);
+ break;
+ case RISCVOp::OPERAND_SIMM8_UNSIGNED:
+ Ok = isInt<8>(Imm);
+ break;
+ case RISCVOp::OPERAND_SIMM10_LSB0000_NONZERO:
+ Ok = isShiftedInt<6, 4>(Imm) && (Imm != 0);
+ break;
+ case RISCVOp::OPERAND_UIMM10_LSB00_NONZERO:
+ Ok = isShiftedUInt<8, 2>(Imm) && (Imm != 0);
+ break;
+ case RISCVOp::OPERAND_UIMM16_NONZERO:
+ Ok = isUInt<16>(Imm) && (Imm != 0);
+ break;
+ case RISCVOp::OPERAND_THREE:
+ Ok = Imm == 3;
+ break;
+ case RISCVOp::OPERAND_FOUR:
+ Ok = Imm == 4;
+ break;
+ case RISCVOp::OPERAND_IMM5_ZIBI:
+ Ok = (isUInt<5>(Imm) && Imm != 0) || Imm == -1;
+ break;
+ // clang-format off
+ CASE_OPERAND_SIMM(5)
+ CASE_OPERAND_SIMM(6)
+ CASE_OPERAND_SIMM(10)
+ CASE_OPERAND_SIMM(11)
+ CASE_OPERAND_SIMM(26)
+ // clang-format on
+ case RISCVOp::OPERAND_SIMM5_PLUS1:
+ Ok = Imm >= -15 && Imm <= 16;
+ break;
+ case RISCVOp::OPERAND_SIMM5_NONZERO:
+ Ok = isInt<5>(Imm) && (Imm != 0);
+ break;
+ case RISCVOp::OPERAND_SIMM6_NONZERO:
+ Ok = Imm != 0 && isInt<6>(Imm);
+ break;
+ case RISCVOp::OPERAND_VTYPEI10:
+ Ok = isUInt<10>(Imm);
+ break;
+ case RISCVOp::OPERAND_VTYPEI11:
+ Ok = isUInt<11>(Imm);
+ break;
+ case RISCVOp::OPERAND_SIMM12_LSB00000:
+ Ok = isShiftedInt<7, 5>(Imm);
+ break;
+ case RISCVOp::OPERAND_SIMM16_NONZERO:
+ Ok = isInt<16>(Imm) && (Imm != 0);
+ break;
+ case RISCVOp::OPERAND_SIMM20_LI:
+ Ok = isInt<20>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMMLOG2XLEN:
+ Ok = STI.is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
+ break;
+ case RISCVOp::OPERAND_UIMMLOG2XLEN_NONZERO:
+ Ok = STI.is64Bit() ? isUInt<6>(Imm) : isUInt<5>(Imm);
+ Ok = Ok && Imm != 0;
+ break;
+ case RISCVOp::OPERAND_CLUI_IMM:
+ Ok = (isUInt<5>(Imm) && Imm != 0) || (Imm >= 0xfffe0 && Imm <= 0xfffff);
+ break;
+ case RISCVOp::OPERAND_RVKRNUM:
+ Ok = Imm >= 0 && Imm <= 10;
+ break;
+ case RISCVOp::OPERAND_RVKRNUM_0_7:
+ Ok = Imm >= 0 && Imm <= 7;
+ break;
+ case RISCVOp::OPERAND_RVKRNUM_1_10:
+ Ok = Imm >= 1 && Imm <= 10;
+ break;
+ case RISCVOp::OPERAND_RVKRNUM_2_14:
+ Ok = Imm >= 2 && Imm <= 14;
+ break;
+ case RISCVOp::OPERAND_RLIST:
+ Ok = Imm >= RISCVZC::RA && Imm <= RISCVZC::RA_S0_S11;
+ break;
+ case RISCVOp::OPERAND_RLIST_S0:
+ Ok = Imm >= RISCVZC::RA_S0 && Imm <= RISCVZC::RA_S0_S11;
+ break;
+ case RISCVOp::OPERAND_STACKADJ:
+ Ok = Imm >= 0 && Imm <= 48 && Imm % 16 == 0;
+ break;
+ case RISCVOp::OPERAND_FRMARG:
+ Ok = RISCVFPRndMode::isValidRoundingMode(Imm);
+ break;
+ case RISCVOp::OPERAND_RTZARG:
+ Ok = Imm == RISCVFPRndMode::RTZ;
+ break;
+ case RISCVOp::OPERAND_COND_CODE:
+ Ok = Imm >= 0 && Imm < RISCVCC::COND_INVALID;
+ break;
+ case RISCVOp::OPERAND_VEC_POLICY:
+ Ok = (Imm & (RISCVVType::TAIL_AGNOSTIC | RISCVVType::MASK_AGNOSTIC)) ==
+ Imm;
+ break;
+ case RISCVOp::OPERAND_SEW:
+ Ok = (isUInt<5>(Imm) && RISCVVType::isValidSEW(1 << Imm));
+ break;
+ case RISCVOp::OPERAND_SEW_MASK:
+ Ok = Imm == 0;
+ break;
+ case RISCVOp::OPERAND_VEC_RM:
+ assert(RISCVII::hasRoundModeOp(Desc.TSFlags));
+ if (RISCVII::usesVXRM(Desc.TSFlags))
+ Ok = isUInt<2>(Imm);
+ else
Ok = RISCVFPRndMode::isValidRoundingMode(Imm);
- break;
- case RISCVOp::OPERAND_RTZARG:
- Ok = Imm == RISCVFPRndMode::RTZ;
- break;
- case RISCVOp::OPERAND_COND_CODE:
- Ok = Imm >= 0 && Imm < RISCVCC::COND_INVALID;
- break;
- case RISCVOp::OPERAND_VEC_POLICY:
- Ok = (Imm &
- (RISCVVType::TAIL_AGNOSTIC | RISCVVType::MASK_AGNOSTIC)) == Imm;
- break;
- case RISCVOp::OPERAND_SEW:
- Ok = (isUInt<5>(Imm) && RISCVVType::isValidSEW(1 << Imm));
- break;
- case RISCVOp::OPERAND_SEW_MASK:
- Ok = Imm == 0;
- break;
- case RISCVOp::OPERAND_VEC_RM:
- assert(RISCVII::hasRoundModeOp(Desc.TSFlags));
- if (RISCVII::usesVXRM(Desc.TSFlags))
- Ok = isUInt<2>(Imm);
- else
- Ok = RISCVFPRndMode::isValidRoundingMode(Imm);
- break;
- case RISCVOp::OPERAND_XSFMM_VTYPE:
- Ok = RISCVVType::isValidXSfmmVType(Imm);
- break;
- }
- if (!Ok) {
- ErrInfo = "Invalid immediate";
- return false;
- }
+ break;
+ case RISCVOp::OPERAND_XSFMM_VTYPE:
+ Ok = RISCVVType::isValidXSfmmVType(Imm);
+ break;
+ }
+ if (!Ok) {
+ ErrInfo = "Invalid immediate";
+ return false;
+ }
+ } else if (OpType == RISCVOp::OPERAND_SIMM12_LO) {
+ // TODO: We could be stricter about what non-register operands are
+ // allowed.
+ if (MO.isReg()) {
+ ErrInfo = "Expected a non-register operand.";
+ return false;
+ }
+ if (MO.isImm() && !isInt<12>(MO.getImm())) {
+ ErrInfo = "Invalid immediate";
+ return false;
+ }
+ } else if (OpType == RISCVOp::OPERAND_UIMM20_LUI ||
+ OpType == RISCVOp::OPERAND_UIMM20_AUIPC) {
+ // TODO: We could be stricter about what non-register operands are
+ // allowed.
+ if (MO.isReg()) {
+ ErrInfo = "Expected a non-register operand.";
+ return false;
+ }
+ if (MO.isImm() && !isUInt<20>(MO.getImm())) {
+ ErrInfo = "Invalid immediate";
+ return false;
+ }
+ } else if (OpType == RISCVOp::OPERAND_BARE_SIMM32) {
+ // TODO: We could be stricter about what non-register operands are
+ // allowed.
+ if (MO.isReg()) {
+ ErrInfo = "Expected a non-register operand.";
+ return false;
+ }
+ if (MO.isImm() && !isInt<32>(MO.getImm())) {
+ ErrInfo = "Invalid immediate";
+ return false;
}
}
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index a27c46ebf3a99..9a4eb12ca0eb0 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -349,6 +349,7 @@ def simm12_lo : RISCVSImmLeafOp<12> {
return isInt<12>(Imm);
return MCOp.isBareSymbolRef();
}];
+ let OperandType = "OPERAND_SIMM12_LO";
}
// A 12-bit signed immediate which cannot fit in 6-bit signed immediate,
@@ -394,9 +395,11 @@ class UImm20OperandMaybeSym : RISCVUImmOp<20> {
def uimm20_lui : UImm20OperandMaybeSym {
let ParserMatchClass = UImmAsmOperand<20, "LUI">;
+ let OperandType = "OPERAND_UIMM20_LUI";
}
def uimm20_auipc : UImm20OperandMaybeSym {
let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;
+ let OperandType = "OPERAND_UIMM20_AUIPC";
}
def uimm20 : RISCVUImmOp<20>;
More information about the llvm-commits
mailing list