[llvm] RISCV: Maintain VL/VTYPE liveness when clearing dead flags in InsertVSETVLI (PR #222862)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 11 00:02:25 PDT 2026


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/222862

Drop the stale VL/VTYPE ranges when a dead flag is cleared.

RISCVInsertVSETVLI marks the VL and VTYPE defs of an explicit VSETVLI as live by
clearing their dead flags, but did not update LiveIntervals. When a def was
previously a dead def, its live range is a zero-length dead-def segment
ending at the def slot; clearing the flag extends the def past that slot without
extending the range leaving a segment that references no instruction.

Co-authored-by: Claude claude-opus-4.8 <noreply at anthropic.com>

>From 94b410e866600f971ef0dfa9852dca77d347f8b8 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Thu, 10 Sep 2026 22:25:39 +0200
Subject: [PATCH] RISCV: Maintain VL/VTYPE liveness when clearing dead flags in
 InsertVSETVLI

Drop the stale VL/VTYPE ranges when a dead flag is cleared.

RISCVInsertVSETVLI marks the VL and VTYPE defs of an explicit VSETVLI as live by
clearing their dead flags, but did not update LiveIntervals. When a def was
previously a dead def, its live range is a zero-length dead-def segment
ending at the def slot; clearing the flag extends the def past that slot without
extending the range leaving a segment that references no instruction.

Co-authored-by: Claude claude-opus-4.8 <noreply at anthropic.com>
---
 llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp  | 10 ++++++
 .../rvv/vsetvli-dead-vl-vtype-liveness.mir    | 33 +++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/rvv/vsetvli-dead-vl-vtype-liveness.mir

diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
index 2333ede15f50d..62b8e9f1e0ef4 100644
--- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
@@ -543,6 +543,16 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) {
       assert(MI.getOperand(3).getReg() == RISCV::VL &&
              MI.getOperand(4).getReg() == RISCV::VTYPE &&
              "Unexpected operands where VL and VTYPE should be");
+
+      if (LIS) {
+        // Clearing a dead flag extends that def past its previous dead-def
+        // slot, so the stale VL/VTYPE range must be dropped.
+        if (MI.getOperand(3).isDead())
+          LIS->removeAllRegUnitsForPhysReg(RISCV::VL);
+        if (MI.getOperand(4).isDead())
+          LIS->removeAllRegUnitsForPhysReg(RISCV::VTYPE);
+      }
+
       MI.getOperand(3).setIsDead(false);
       MI.getOperand(4).setIsDead(false);
       PrefixTransparent = false;
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsetvli-dead-vl-vtype-liveness.mir b/llvm/test/CodeGen/RISCV/rvv/vsetvli-dead-vl-vtype-liveness.mir
new file mode 100644
index 0000000000000..b8988ac10ec21
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/vsetvli-dead-vl-vtype-liveness.mir
@@ -0,0 +1,33 @@
+# REQUIRES: asserts
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=liveintervals,riscv-insert-vsetvli \
+# RUN:   -precompute-phys-liveness -verify-machineinstrs -o - %s | FileCheck %s
+
+# Clearing the dead flags on an VSETVLI's VL and VTYPE defs must
+# update their physreg live ranges. Otherwise a previously-dead def
+# leaves a zero-length dead-def segment referencing the (now non-dead)
+# def slot. -precompute-phys-liveness forces the VL/VTYPE ranges to
+# exist so the stale segment is exercised.
+
+---
+name:            bad_removal
+tracksRegLiveness: true
+isSSA:           false
+body:             |
+  bb.0:
+    liveins: $v8
+
+    ; CHECK-LABEL: name: bad_removal
+    ; CHECK: liveins: $v8
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[PseudoVSETIVLI:%[0-9]+]]:gpr = PseudoVSETIVLI 16, 216 /* e64, m1, ta, ma */, implicit-def $vl, implicit-def $vtype
+    ; CHECK-NEXT: [[PseudoVMV_X_S:%[0-9]+]]:gpr = PseudoVMV_X_S renamable $v8, 6 /* e64 */, implicit $vtype
+    ; CHECK-NEXT: [[ADD:%[0-9]+]]:gpr = ADD [[PseudoVMV_X_S]], [[PseudoVSETIVLI]]
+    ; CHECK-NEXT: $x10 = COPY [[ADD]]
+    ; CHECK-NEXT: PseudoRET implicit $x10
+    %1:gpr = PseudoVMV_X_S killed renamable $v8, 6 /* e64 */
+    %2:gpr = PseudoVSETIVLI 16, 216 /* e64, m1, ta, ma */, implicit-def dead $vl, implicit-def dead $vtype
+    %3:gpr = ADD %1, %2
+    $x10 = COPY %3
+    PseudoRET implicit $x10
+...



More information about the llvm-commits mailing list