[llvm] [RISCV] Handle sign_extend of i32 in insert_vector_elt for RV32 (PR #185548)

Jim Lin via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 9 18:04:37 PDT 2026


https://github.com/tclin914 created https://github.com/llvm/llvm-project/pull/185548

On RV32 with <N x i64> vectors, inserting a value that is a
sign_extend of an i32 only uses the lower 32 bits, so it can be
lowered without scalar legalization, same as i32 constants.

>From a5832fd72a462faa9655b51ad1406393f2bccf03 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Mon, 9 Mar 2026 15:20:11 +0800
Subject: [PATCH 1/2] [RISCV] Pre-commit test

---
 .../CodeGen/RISCV/rvv/fixed-vectors-insert.ll | 25 +++++++++++++++++++
 .../CodeGen/RISCV/rvv/insertelt-int-rv32.ll   | 15 +++++++++++
 2 files changed, 40 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert.ll
index 79286c0304e0c..26b03ddc71e2e 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert.ll
@@ -574,6 +574,31 @@ define <8 x i64> @insertelt_v8i64_0(<8 x i64> %a, ptr %x) {
   ret <8 x i64> %b
 }
 
+define <8 x i64> @insertelt_v8i64_sext_0(<8 x i64> %a, ptr %x, i32 signext %elt) {
+; RV32-LABEL: insertelt_v8i64_sext_0:
+; RV32:       # %bb.0:
+; RV32-NEXT:    srai a0, a1, 31
+; RV32-NEXT:    vsetivli zero, 2, e32, m1, tu, ma
+; RV32-NEXT:    vslide1down.vx v8, v8, a1
+; RV32-NEXT:    vslide1down.vx v8, v8, a0
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: insertelt_v8i64_sext_0:
+; RV64:       # %bb.0:
+; RV64-NEXT:    vsetivli zero, 8, e64, m1, tu, ma
+; RV64-NEXT:    vmv.s.x v8, a1
+; RV64-NEXT:    ret
+;
+; VISNI-LABEL: insertelt_v8i64_sext_0:
+; VISNI:       # %bb.0:
+; VISNI-NEXT:    vsetivli zero, 8, e64, m1, tu, ma
+; VISNI-NEXT:    vmv.s.x v8, a1
+; VISNI-NEXT:    ret
+  %sext = sext i32 %elt to i64
+  %b = insertelement <8 x i64> %a, i64 %sext, i32 0
+  ret <8 x i64> %b
+}
+
 define void @insertelt_v8i64_0_store(ptr %x) {
 ; RV32-LABEL: insertelt_v8i64_0_store:
 ; RV32:       # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rvv/insertelt-int-rv32.ll b/llvm/test/CodeGen/RISCV/rvv/insertelt-int-rv32.ll
index c3cc90c6a8de3..10cb3d42b6475 100644
--- a/llvm/test/CodeGen/RISCV/rvv/insertelt-int-rv32.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/insertelt-int-rv32.ll
@@ -838,3 +838,18 @@ define <vscale x 2 x i64> @insertelt_nxv2i64_idx_cn1(<vscale x 2 x i64> %v, i32
   %r = insertelement <vscale x 2 x i64> %v, i64 -1, i32 %idx
   ret <vscale x 2 x i64> %r
 }
+
+define <vscale x 2 x i64> @insertelt_nxv2i64_sext(<vscale x 2 x i64> %v, i32 signext %elt, i32 %idx) {
+; CHECK-LABEL: insertelt_nxv2i64_sext:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    srai a1, a0, 31
+; CHECK-NEXT:    vsetivli zero, 2, e32, m2, ta, ma
+; CHECK-NEXT:    vslide1down.vx v10, v8, a0
+; CHECK-NEXT:    vslide1down.vx v10, v10, a1
+; CHECK-NEXT:    vsetivli zero, 4, e64, m2, tu, ma
+; CHECK-NEXT:    vslideup.vi v8, v10, 3
+; CHECK-NEXT:    ret
+  %sext = sext i32 %elt to i64
+  %r = insertelement <vscale x 2 x i64> %v, i64 %sext, i32 3
+  ret <vscale x 2 x i64> %r
+}

>From 78b4a7ba6586b444b814cd9d32ce7a166a9527d0 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Fri, 6 Mar 2026 11:08:16 +0800
Subject: [PATCH 2/2] [RISCV] Handle sign_extend of i32 in insert_vector_elt
 for RV32

On RV32 with <N x i64> vectors, inserting a value that is a
sign_extend of an i32 only uses the lower 32 bits, so it can be
lowered without scalar legalization, same as i32 constants.
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp    | 18 ++++++++++++------
 .../CodeGen/RISCV/rvv/fixed-vectors-insert.ll  | 18 +++++-------------
 .../CodeGen/RISCV/rvv/insertelt-int-rv32.ll    |  5 +----
 3 files changed, 18 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 808c8b2be818b..5773ec754d2b7 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -10990,13 +10990,19 @@ SDValue RISCVTargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
   bool IsLegalInsert = Subtarget.is64Bit() || Val.getValueType() != MVT::i64;
   // Even i64-element vectors on RV32 can be lowered without scalar
   // legalization if the most-significant 32 bits of the value are not affected
-  // by the sign-extension of the lower 32 bits.
-  // TODO: We could also catch sign extensions of a 32-bit value.
-  if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
-    const auto *CVal = cast<ConstantSDNode>(Val);
-    if (isInt<32>(CVal->getSExtValue())) {
+  // by the sign-extension of the lower 32 bits. This applies to i32 constants
+  // and sign_extend of i32 values.
+  if (!IsLegalInsert) {
+    if (isa<ConstantSDNode>(Val)) {
+      const auto *CVal = cast<ConstantSDNode>(Val);
+      if (isInt<32>(CVal->getSExtValue())) {
+        IsLegalInsert = true;
+        Val = DAG.getSignedConstant(CVal->getSExtValue(), DL, MVT::i32);
+      }
+    } else if (Val.getOpcode() == ISD::SIGN_EXTEND &&
+               Val.getOperand(0).getValueType() == MVT::i32) {
       IsLegalInsert = true;
-      Val = DAG.getSignedConstant(CVal->getSExtValue(), DL, MVT::i32);
+      Val = Val.getOperand(0);
     }
   }
 
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert.ll
index 26b03ddc71e2e..b95a12ff62571 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert.ll
@@ -575,19 +575,11 @@ define <8 x i64> @insertelt_v8i64_0(<8 x i64> %a, ptr %x) {
 }
 
 define <8 x i64> @insertelt_v8i64_sext_0(<8 x i64> %a, ptr %x, i32 signext %elt) {
-; RV32-LABEL: insertelt_v8i64_sext_0:
-; RV32:       # %bb.0:
-; RV32-NEXT:    srai a0, a1, 31
-; RV32-NEXT:    vsetivli zero, 2, e32, m1, tu, ma
-; RV32-NEXT:    vslide1down.vx v8, v8, a1
-; RV32-NEXT:    vslide1down.vx v8, v8, a0
-; RV32-NEXT:    ret
-;
-; RV64-LABEL: insertelt_v8i64_sext_0:
-; RV64:       # %bb.0:
-; RV64-NEXT:    vsetivli zero, 8, e64, m1, tu, ma
-; RV64-NEXT:    vmv.s.x v8, a1
-; RV64-NEXT:    ret
+; CHECK-LABEL: insertelt_v8i64_sext_0:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 8, e64, m1, tu, ma
+; CHECK-NEXT:    vmv.s.x v8, a1
+; CHECK-NEXT:    ret
 ;
 ; VISNI-LABEL: insertelt_v8i64_sext_0:
 ; VISNI:       # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rvv/insertelt-int-rv32.ll b/llvm/test/CodeGen/RISCV/rvv/insertelt-int-rv32.ll
index 10cb3d42b6475..3daf7dba85ba0 100644
--- a/llvm/test/CodeGen/RISCV/rvv/insertelt-int-rv32.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/insertelt-int-rv32.ll
@@ -842,11 +842,8 @@ define <vscale x 2 x i64> @insertelt_nxv2i64_idx_cn1(<vscale x 2 x i64> %v, i32
 define <vscale x 2 x i64> @insertelt_nxv2i64_sext(<vscale x 2 x i64> %v, i32 signext %elt, i32 %idx) {
 ; CHECK-LABEL: insertelt_nxv2i64_sext:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    srai a1, a0, 31
-; CHECK-NEXT:    vsetivli zero, 2, e32, m2, ta, ma
-; CHECK-NEXT:    vslide1down.vx v10, v8, a0
-; CHECK-NEXT:    vslide1down.vx v10, v10, a1
 ; CHECK-NEXT:    vsetivli zero, 4, e64, m2, tu, ma
+; CHECK-NEXT:    vmv.s.x v10, a0
 ; CHECK-NEXT:    vslideup.vi v8, v10, 3
 ; CHECK-NEXT:    ret
   %sext = sext i32 %elt to i64



More information about the llvm-commits mailing list