[llvm] cfe9def - [RISCV][Verifier] Check operands and result type of RISC-V vsetvli/vsetvlimax (#218594)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 25 20:43:11 PDT 2026


Author: Pengcheng Wang
Date: 2026-08-26T03:43:06Z
New Revision: cfe9def9a4149c7aa1db2dcb7adcef439d763d63

URL: https://github.com/llvm/llvm-project/commit/cfe9def9a4149c7aa1db2dcb7adcef439d763d63
DIFF: https://github.com/llvm/llvm-project/commit/cfe9def9a4149c7aa1db2dcb7adcef439d763d63.diff

LOG: [RISCV][Verifier] Check operands and result type of RISC-V vsetvli/vsetvlimax (#218594)

The result of `llvm.riscv.vsetvli/vsetvlimax` models VLMAX (or a VL bounded
by it) and is only defined for XLen, so the result type must be i32 or i64.
Narrower types cannot represent the architectural VLMAX range of [1, 65536]
that value analyses rely on.

Also check that the VSEW and VLMUL immediate operands encode a valid
SEW/LMUL pair (VSEW <= 3, VLMUL != reserved), so that consumers can
assume a well-formed vtype.

Assisted-by: TRAE CLI (Opus 4.8)

Added: 
    llvm/test/Verifier/RISCV/vsetvli.ll

Modified: 
    llvm/lib/IR/Verifier.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 9cef4b05f19e5..7b78acc5aba56 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -99,6 +99,7 @@
 #include "llvm/IR/IntrinsicsAArch64.h"
 #include "llvm/IR/IntrinsicsARM.h"
 #include "llvm/IR/IntrinsicsNVPTX.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MemoryModelRelaxationAnnotations.h"
@@ -126,6 +127,7 @@
 #include "llvm/Support/ModRef.h"
 #include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/Transforms/Coroutines/CoroInstr.h"
 #include <algorithm>
@@ -6976,6 +6978,26 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
           Call);
     break;
   }
+  case Intrinsic::riscv_vsetvli:
+  case Intrinsic::riscv_vsetvlimax: {
+    // The result models VLMAX (or a VL bounded by it) and is only defined for
+    // XLen (i32/i64). Narrower types cannot represent the architectural VLMAX
+    // range of [1, 65536], which value analyses rely on.
+    Check(Call.getType()->isIntegerTy(32) || Call.getType()->isIntegerTy(64),
+          "llvm.riscv.vsetvli/vsetvlimax result must be i32 or i64", &Call);
+
+    // VSEW and VLMUL select the vtype and must encode a valid SEW/LMUL pair.
+    bool HasAVL = ID == Intrinsic::riscv_vsetvli;
+    unsigned Offset = HasAVL ? 1 : 0;
+    uint64_t VSEW =
+        cast<ConstantInt>(Call.getArgOperand(Offset))->getZExtValue();
+    uint64_t VLMUL =
+        cast<ConstantInt>(Call.getArgOperand(Offset + 1))->getZExtValue();
+    Check(VSEW <= 3, "llvm.riscv.vsetvli/vsetvlimax VSEW must be 0-3", &Call);
+    Check(VLMUL <= 7 && VLMUL != RISCVVType::LMUL_RESERVED,
+          "llvm.riscv.vsetvli/vsetvlimax VLMUL is reserved", &Call);
+    break;
+  }
   case Intrinsic::callbr_landingpad: {
     const auto *CBR = dyn_cast<CallBrInst>(Call.getOperand(0));
     Check(CBR, "intrinstic requires callbr operand", &Call);

diff  --git a/llvm/test/Verifier/RISCV/vsetvli.ll b/llvm/test/Verifier/RISCV/vsetvli.ll
new file mode 100644
index 0000000000000..82c13a4416c67
--- /dev/null
+++ b/llvm/test/Verifier/RISCV/vsetvli.ll
@@ -0,0 +1,25 @@
+; RUN: not opt -passes=verify -S < %s 2>&1 | FileCheck %s
+
+; CHECK: llvm.riscv.vsetvli/vsetvlimax result must be i32 or i64
+define i16 @narrow_result() {
+  %vl = call i16 @llvm.riscv.vsetvlimax.i16(i16 0, i16 3)
+  ret i16 %vl
+}
+
+; CHECK: llvm.riscv.vsetvli/vsetvlimax VSEW must be 0-3
+define i64 @bad_vsew() {
+  %vl = call i64 @llvm.riscv.vsetvlimax.i64(i64 5, i64 0)
+  ret i64 %vl
+}
+
+; CHECK: llvm.riscv.vsetvli/vsetvlimax VLMUL is reserved
+define i64 @reserved_vlmul() {
+  %vl = call i64 @llvm.riscv.vsetvlimax.i64(i64 0, i64 4)
+  ret i64 %vl
+}
+
+; CHECK: llvm.riscv.vsetvli/vsetvlimax VSEW must be 0-3
+define i64 @vsetvli_bad_vsew(i64 %avl) {
+  %vl = call i64 @llvm.riscv.vsetvli.i64(i64 %avl, i64 7, i64 0)
+  ret i64 %vl
+}


        


More information about the llvm-commits mailing list