[llvm] fb40f2b - [RISCV] Use getNamedOperandIdx in the RVVConstraint checks. (#181936)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 18 09:14:24 PST 2026
Author: Craig Topper
Date: 2026-02-18T09:14:19-08:00
New Revision: fb40f2be557fe0c539d4cee4d64b6135f020e898
URL: https://github.com/llvm/llvm-project/commit/fb40f2be557fe0c539d4cee4d64b6135f020e898
DIFF: https://github.com/llvm/llvm-project/commit/fb40f2be557fe0c539d4cee4d64b6135f020e898.diff
LOG: [RISCV] Use getNamedOperandIdx in the RVVConstraint checks. (#181936)
Instead of using heuristics to find the vd, vs1, vs2, and vm operands,
look them up by name.
In the course of doing this, I found a few issues that have been fixed
in separate PRs, #181887 and #181895
The constraint on SF_VQMACC_2x8x2 had to be updated from Vs2 to Vs1
because the heuristics were finding the wrong operand name before so
the constraint had been adjusted to compensate.
We still need a bit of a hack to find the destination operand SMLoc for
some XSfvcp instructions.
Added:
Modified:
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
llvm/lib/Target/RISCV/RISCVInstrFormatsV.td
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
llvm/lib/Target/RISCV/RISCVInstrInfo.h
llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
llvm/lib/Target/RISCV/RISCVInstrInfoXRivos.td
llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 521b14e498af5..4168cb473fdf1 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -3829,68 +3829,63 @@ bool RISCVAsmParser::validateInstruction(MCInst &Inst,
if (!(MCID.TSFlags & RISCVII::RVVConstraintMask))
return false;
- if (Opcode == RISCV::SF_VC_V_XVW || Opcode == RISCV::SF_VC_V_IVW ||
- Opcode == RISCV::SF_VC_V_FVW || Opcode == RISCV::SF_VC_V_VVW) {
- // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for SF_VC_V_XVW.
- MCRegister VCIXDst = Inst.getOperand(0).getReg();
- SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
- if (MCID.TSFlags & RISCVII::VS1Constraint) {
- MCRegister VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
- if (VCIXDst == VCIXRs1)
- return Error(VCIXDstLoc, "the destination vector register group cannot"
- " overlap the source vector register group");
- }
- if (MCID.TSFlags & RISCVII::VS2Constraint) {
- MCRegister VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
- if (VCIXDst == VCIXRs2)
- return Error(VCIXDstLoc, "the destination vector register group cannot"
- " overlap the source vector register group");
- }
- return false;
- }
+ int DestIdx = RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vd);
+ MCRegister DestReg = Inst.getOperand(DestIdx).getReg();
- MCRegister DestReg = Inst.getOperand(0).getReg();
- unsigned Offset = 0;
- int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);
- if (TiedOp == 0)
- Offset = 1;
+ // Operands[1] or Operands[2] will be the first operand, DestReg.
+ const MCParsedAsmOperand *ParsedOp = Operands[1].get();
+ if (!ParsedOp->isReg()) {
+ // XSfvcp instructions may have an immediate before vd.
+ // FIXME: Is there a better way to do this?
+ ParsedOp = Operands[2].get();
+ }
+ assert(ParsedOp->getReg() == DestReg && "Can't find parsed dest operand");
+ SMLoc Loc = ParsedOp->getStartLoc();
- // Operands[1] will be the first operand, DestReg.
- SMLoc Loc = Operands[1]->getStartLoc();
if (MCID.TSFlags & RISCVII::VS2Constraint) {
- MCRegister CheckReg = Inst.getOperand(Offset + 1).getReg();
+ int VS2Idx =
+ RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs2);
+ assert(VS2Idx >= 0 && "No vs2 operand?");
+ MCRegister CheckReg = Inst.getOperand(VS2Idx).getReg();
if (DestReg == CheckReg)
return Error(Loc, "the destination vector register group cannot overlap"
" the source vector register group");
}
- if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {
- MCRegister CheckReg = Inst.getOperand(Offset + 2).getReg();
- if (DestReg == CheckReg)
- return Error(Loc, "the destination vector register group cannot overlap"
- " the source vector register group");
+ if (MCID.TSFlags & RISCVII::VS1Constraint) {
+ int VS1Idx =
+ RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vs1);
+ // FIXME: The vs1 constraint is used on scalar and imm instructions so we
+ // need to check that the operand exists.
+ if (VS1Idx >= 0) {
+ MCRegister CheckReg = Inst.getOperand(VS1Idx).getReg();
+ if (DestReg == CheckReg)
+ return Error(Loc, "the destination vector register group cannot overlap"
+ " the source vector register group");
+ }
}
- if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
- // vadc, vsbc are special cases. These instructions have no mask register.
- // The destination register could not be V0.
- if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
- Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
- Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
- Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
- Opcode == RISCV::VMERGE_VXM)
- return Error(Loc, "the destination vector register group cannot be V0");
-
- // Regardless masked or unmasked version, the number of operands is the
- // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
- // actually. We need to check the last operand to ensure whether it is
- // masked or not.
- MCRegister CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
- assert((CheckReg == RISCV::V0 || !CheckReg) &&
- "Unexpected register for mask operand");
- if (DestReg == CheckReg)
- return Error(Loc, "the destination vector register group cannot overlap"
- " the mask register");
+ if (MCID.TSFlags & RISCVII::VMConstraint) {
+ int VMIdx = RISCV::getNamedOperandIdx(Inst.getOpcode(), RISCV::OpName::vm);
+ assert(VMIdx >= 0 && "No vm operand?");
+
+ if (DestReg == RISCV::V0) {
+ if (MCID.operands()[Inst.getNumOperands() - 1].OperandType !=
+ RISCVOp::OPERAND_VMASK)
+ return Error(Loc, "the destination vector register group cannot be V0");
+
+ // Regardless masked or unmasked version, the number of operands is the
+ // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
+ // actually. We need to check the operand to see whether it is masked or
+ // not.
+ MCRegister CheckReg = Inst.getOperand(VMIdx).getReg();
+ assert((!CheckReg.isValid() || CheckReg == RISCV::V0) &&
+ "Unexpected mask operand register");
+ if (CheckReg.isValid())
+ return Error(Loc, "the destination vector register group cannot overlap"
+ " the mask register");
+ }
}
+
return false;
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
index 38d154d90d7e0..4cb41fc92c4ba 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
@@ -35,6 +35,7 @@
#define GET_INSTRINFO_MC_DESC
#define ENABLE_INSTR_PREDICATE_VERIFIER
+#define GET_INSTRINFO_NAMED_OPS
#include "RISCVGenInstrInfo.inc"
#define GET_REGINFO_MC_DESC
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
index d1733886637f8..39a34f6ae434e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h
@@ -53,6 +53,7 @@ void updateCZceFeatureImplications(MCSubtargetInfo &STI);
// Defines symbolic names for RISC-V instructions.
#define GET_INSTRINFO_ENUM
#define GET_INSTRINFO_MC_HELPER_DECLS
+#define GET_INSTRINFO_OPERAND_ENUM
#include "RISCVGenInstrInfo.inc"
#define GET_SUBTARGETINFO_ENUM
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormatsV.td b/llvm/lib/Target/RISCV/RISCVInstrFormatsV.td
index 8aa3fb341e3b4..c007838d31dfe 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormatsV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormatsV.td
@@ -102,6 +102,8 @@ class RVInstVBase<bits<6> funct6, RISCVVFormat opv, dag outs, dag ins,
let Uses = [VL, VTYPE];
let RVVConstraint = VMConstraint;
+
+ let UseNamedOperandTable = true;
}
class RVInstVV<bits<6> funct6, RISCVVFormat opv, dag outs, dag ins,
@@ -160,6 +162,8 @@ class RVInstVUnaryRd<bits<6> funct6, bits<5> vs1, RISCVVFormat opv, dag outs,
let Uses = [VL, VTYPE];
let RVVConstraint = NoConstraint;
+
+ let UseNamedOperandTable = true;
}
class RVInstVLoadBase<bits<3> nf, RISCVWidth width, RISCVMOP mop,
@@ -181,6 +185,8 @@ class RVInstVLoadBase<bits<3> nf, RISCVWidth width, RISCVMOP mop,
let Uses = [VL, VTYPE];
let RVVConstraint = VMConstraint;
+
+ let UseNamedOperandTable = true;
}
class RVInstVLU<bits<3> nf, RISCVWidth width, RISCVLUMOP lumop, dag outs,
@@ -224,6 +230,8 @@ class RVInstVStoreBase<bits<3> nf, RISCVWidth width, RISCVMOP mop, dag outs,
let Inst{6-0} = OPC_STORE_FP.Value;
let Uses = [VL, VTYPE];
+
+ let UseNamedOperandTable = true;
}
class RVInstVSU<bits<3> nf, RISCVWidth width, RISCVSUMOP sumop, dag outs,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 2b496b1b20318..98561a9345daf 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -42,7 +42,6 @@ using namespace llvm;
#include "RISCVGenCompressInstEmitter.inc"
#define GET_INSTRINFO_CTOR_DTOR
-#define GET_INSTRINFO_NAMED_OPS
#include "RISCVGenInstrInfo.inc"
#define DEBUG_TYPE "riscv-instr-info"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 2932efffdb814..cfe2e5c474fbd 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -19,7 +19,6 @@
#include "llvm/IR/DiagnosticInfo.h"
#define GET_INSTRINFO_HEADER
-#define GET_INSTRINFO_OPERAND_ENUM
#include "RISCVGenInstrInfo.inc"
#include "RISCVGenRegisterInfo.inc"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 1b8cf3ddf7d2e..8f97e81537f1b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -380,6 +380,8 @@ class NDSRVInstVSINTLN<bits<5> funct5, string opcodestr>
let mayLoad = 1;
let mayStore = 0;
let Uses = [VL, VTYPE];
+
+ let UseNamedOperandTable = true;
}
class NDSRVInstVSINTCvt<bits<5> fucnt5, string opcodestr>
@@ -401,6 +403,8 @@ class NDSRVInstVSINTCvt<bits<5> fucnt5, string opcodestr>
let mayStore = 0;
let Uses = [FRM, VL, VTYPE];
let RVVConstraint = VMConstraint;
+
+ let UseNamedOperandTable = true;
}
class NDSRVInstBFHCvt<bits<7> funct7, bits<5> rs1val, DAGOperand rdty,
@@ -435,6 +439,8 @@ class NDSRVInstVFPMAD<bits<6> funct6, string opcodestr>
let mayStore = 0;
let RVVConstraint = VMConstraint;
+
+ let UseNamedOperandTable = true;
}
class NDSRVInstVD4DOT<bits<6> funct6, string opcodestr>
@@ -458,6 +464,8 @@ class NDSRVInstVD4DOT<bits<6> funct6, string opcodestr>
let mayStore = 0;
let RVVConstraint = VMConstraint;
+
+ let UseNamedOperandTable = true;
}
class NDSRVInstVBFHCvt<bits<5> vs1, string opcodestr>
@@ -477,6 +485,8 @@ class NDSRVInstVBFHCvt<bits<5> vs1, string opcodestr>
let mayStore = 0;
let Uses = [VL, VTYPE];
+
+ let UseNamedOperandTable = true;
}
class NDSRVInstVLN<bits<5> funct5, string opcodestr>
@@ -500,6 +510,8 @@ class NDSRVInstVLN<bits<5> funct5, string opcodestr>
let Uses = [VL, VTYPE];
let RVVConstraint = VMConstraint;
+
+ let UseNamedOperandTable = true;
}
class VPseudoVLN8NoMask<VReg RetClass, bit U> :
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXRivos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXRivos.td
index 51506f40d3811..601270d3be4ee 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXRivos.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXRivos.td
@@ -29,6 +29,8 @@ class CustomRivosVXI<bits<6> funct6, RISCVVFormat opv, dag outs, dag ins,
let Uses = [VL, VTYPE];
let RVVConstraint = NoConstraint;
let Constraints = "$vd = $vd_wb";
+
+ let UseNamedOperandTable = true;
}
class CustomRivosXVI<bits<6> funct6, RISCVVFormat opv, dag outs, dag ins,
@@ -49,6 +51,8 @@ class CustomRivosXVI<bits<6> funct6, RISCVVFormat opv, dag outs, dag ins,
let Uses = [VL, VTYPE];
let RVVConstraint = NoConstraint;
+
+ let UseNamedOperandTable = true;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td
index bc65db1f77ffb..9cc5dbf595871 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td
@@ -132,6 +132,8 @@ class RVInstVCCustom2Base<VCIXInfo info>
let RVVConstraint = info.RVVConstraint;
let ElementsDependOn = EltDepsVLMask;
let ReadsPastVL = 1;
+
+ let UseNamedOperandTable = true;
}
// VCIX instructions with GPR rs1 operand
@@ -254,7 +256,7 @@ let Predicates = [HasVendorXSfvfexpa], DecoderNamespace = "XSfvector" in {
}
let Predicates = [HasVendorXSfvqmaccdod], DecoderNamespace = "XSfvector",
- DestEEW = EEWSEWx4, RVVConstraint=VS2Constraint in {
+ DestEEW = EEWSEWx4, RVVConstraint=VS1Constraint in {
def SF_VQMACCU_2x8x2 : CustomSiFiveVMACC<0b101100, OPMVV, "sf.vqmaccu.2x8x2">;
def SF_VQMACC_2x8x2 : CustomSiFiveVMACC<0b101101, OPMVV, "sf.vqmacc.2x8x2">;
def SF_VQMACCUS_2x8x2 : CustomSiFiveVMACC<0b101110, OPMVV, "sf.vqmaccus.2x8x2">;
More information about the llvm-commits
mailing list