[llvm] [LoongArch] Fix crash on SIGN_EXTEND of non-simple vector types (PR #222250)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 00:02:14 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-loongarch

Author: wanglei (wangleiat)

<details>
<summary>Changes</summary>

Custom lowering of ISD::SIGN_EXTEND assumed a simple vector source,
which does not hold for e.g. the <4 x i24> mask promoted from an i24
vector compare. Bail out so the type legalizer falls back to the
default path; also guard lowerSIGN_EXTEND_VECTOR_INREG.

Fixes #<!-- -->222088


---
Full diff: https://github.com/llvm/llvm-project/pull/222250.diff


2 Files Affected:

- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+14-4) 
- (added) llvm/test/CodeGen/LoongArch/lsx/pr222088.ll (+53) 


``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 07f6a438bbb1b..9f3f16426e0e4 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -1021,6 +1021,11 @@ SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
     SDValue Op, SelectionDAG &DAG) const {
   SDLoc DL(Op);
   SDValue Src = Op.getOperand(0);
+
+  // Only whole 128-bit vectors of simple element types can be lowered this
+  // way; fall back to the default lowering for other sources.
+  if (!Src.getValueType().isSimple())
+    return SDValue();
   MVT SrcVT = Src.getSimpleValueType();
   MVT DstVT = Op.getSimpleValueType();
 
@@ -6003,15 +6008,20 @@ void LoongArchTargetLowering::ReplaceNodeResults(
 
     EVT DstVT = N->getValueType(0);
     SDValue Src = N->getOperand(0);
-    MVT SrcVT = Src.getSimpleValueType();
+
+    // The VSLTI + VILVL/VILVH expansion below only supports simple vector
+    // sources no wider than 128 bits. Fall back to the default legalization
+    // for anything else, e.g. when the mask of an i24 vector compare is
+    // sign-extended, the promoted <4 x i24> source is not a simple type.
+    EVT SrcEVT = Src.getValueType();
+    if (!SrcEVT.isSimple() || SrcEVT.getSizeInBits() > 128)
+      return;
+    MVT SrcVT = SrcEVT.getSimpleVT();
 
     unsigned SrcEltBits = SrcVT.getScalarSizeInBits();
     unsigned DstEltBits = DstVT.getScalarSizeInBits();
     unsigned NumElts = DstVT.getVectorNumElements();
 
-    if (SrcVT.getSizeInBits() > 128)
-      return;
-
     if (!DstVT.isVector() || DstVT.getSizeInBits() <= 128)
       return;
 
diff --git a/llvm/test/CodeGen/LoongArch/lsx/pr222088.ll b/llvm/test/CodeGen/LoongArch/lsx/pr222088.ll
new file mode 100644
index 0000000000000..020e5e7793c75
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lsx/pr222088.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx %s -o - | FileCheck %s
+
+define void @sext_v4i24_mask(ptr %src, ptr %dst) {
+; CHECK-LABEL: sext_v4i24_mask:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    ld.b $a2, $a0, 5
+; CHECK-NEXT:    ld.hu $a3, $a0, 3
+; CHECK-NEXT:    ld.b $a4, $a0, 2
+; CHECK-NEXT:    ld.hu $a5, $a0, 0
+; CHECK-NEXT:    slli.d $a2, $a2, 16
+; CHECK-NEXT:    or $a2, $a3, $a2
+; CHECK-NEXT:    slli.d $a3, $a4, 16
+; CHECK-NEXT:    or $a3, $a5, $a3
+; CHECK-NEXT:    ld.b $a4, $a0, 8
+; CHECK-NEXT:    vinsgr2vr.w $vr0, $a3, 0
+; CHECK-NEXT:    vinsgr2vr.w $vr0, $a2, 1
+; CHECK-NEXT:    ld.hu $a2, $a0, 6
+; CHECK-NEXT:    slli.d $a3, $a4, 16
+; CHECK-NEXT:    ld.b $a4, $a0, 11
+; CHECK-NEXT:    ld.hu $a0, $a0, 9
+; CHECK-NEXT:    or $a2, $a2, $a3
+; CHECK-NEXT:    vinsgr2vr.w $vr0, $a2, 2
+; CHECK-NEXT:    slli.d $a2, $a4, 16
+; CHECK-NEXT:    or $a0, $a0, $a2
+; CHECK-NEXT:    vinsgr2vr.w $vr0, $a0, 3
+; CHECK-NEXT:    vrepli.b $vr1, 0
+; CHECK-NEXT:    vslt.w $vr0, $vr1, $vr0
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; CHECK-NEXT:    vinsgr2vr.d $vr2, $a0, 0
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; CHECK-NEXT:    vinsgr2vr.d $vr2, $a0, 1
+; CHECK-NEXT:    vslli.d $vr2, $vr2, 40
+; CHECK-NEXT:    vsrai.d $vr2, $vr2, 40
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 2
+; CHECK-NEXT:    vinsgr2vr.d $vr3, $a0, 0
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 3
+; CHECK-NEXT:    vinsgr2vr.d $vr3, $a0, 1
+; CHECK-NEXT:    vslli.d $vr0, $vr3, 40
+; CHECK-NEXT:    vsrai.d $vr0, $vr0, 40
+; CHECK-NEXT:    vrepli.d $vr3, 5
+; CHECK-NEXT:    vbitsel.v $vr0, $vr1, $vr3, $vr0
+; CHECK-NEXT:    vbitsel.v $vr1, $vr1, $vr3, $vr2
+; CHECK-NEXT:    vst $vr1, $a1, 0
+; CHECK-NEXT:    vst $vr0, $a1, 16
+; CHECK-NEXT:    ret
+entry:
+  %1 = load <4 x i24>, ptr %src
+  %2 = icmp sgt <4 x i24> %1, zeroinitializer
+  %3 = select <4 x i1> %2, <4 x i64> splat (i64 5), <4 x i64> zeroinitializer
+  store <4 x i64> %3, ptr %dst
+  ret void
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/222250


More information about the llvm-commits mailing list