[llvm] [LoongArch] Add LASX sext_invec pattern for v16i8 to v4i64 (PR #219350)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 19:53:34 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-vectorizers

Author: Oscar Priego (Opriego)

<details>
<summary>Changes</summary>

## Summary

Add the missing LASX SelectionDAG pattern for:

    v4i64 (sext_invec v16i8)

The pattern lowers through `VEXT2XV_D_B` with `SUBREG_TO_REG`, consistent with the neighboring LASX extension patterns.

This fixes #<!-- -->219224.

## Testing

- Added a regression test in `llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll`.
- Verified the test passes for both LA32 and LA64.
- Verified the reduced reproducer from #<!-- -->219224 no longer fails and exits successfully.

Fixes #<!-- -->219224


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


4 Files Affected:

- (modified) llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td (+3) 
- (modified) llvm/lib/Transforms/Vectorize/VectorCombine.cpp (+9-2) 
- (modified) llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll (+13) 
- (modified) llvm/test/Transforms/VectorCombine/deinterleave-interleave-pairs.ll (+35) 


``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index 8af1111966785..7e3b30ea6b109 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -2361,6 +2361,9 @@ def : Pat<(v4i32 (sext_invec v16i8:$vj)),
 def : Pat<(v4i32 (sext_invec v8i16:$vj)),
           (v4i32 (EXTRACT_SUBREG (VEXT2XV_W_H (SUBREG_TO_REG v8i16:$vj, sub_128)),
                                  sub_128))>;
+def : Pat<(v4i64 (sext_invec v16i8:$vj)),
+          (v4i64 (VEXT2XV_D_B
+                    (SUBREG_TO_REG v16i8:$vj, sub_128)))>;
 def : Pat<(v4i64 (sext_invec v32i8:$xj)), (v4i64 (VEXT2XV_D_B v32i8:$xj))>;
 def : Pat<(v4i64 (sext_invec v16i16:$xj)), (v4i64 (VEXT2XV_D_H v16i16:$xj))>;
 def : Pat<(v4i64 (sext_invec v8i32:$xj)), (v4i64 (VEXT2XV_D_W v8i32:$xj))>;
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index d19894d57c058..7da3121a35998 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -6153,8 +6153,15 @@ bool VectorCombine::foldDeinterleaveInterleavePair(Instruction &I) {
     unsigned ChainOperand = CurrentUses.front()->getOperandNo();
     if (any_of(CurrentUses, [&](Use *U) {
           auto *Inst = cast<Instruction>(U->getUser());
-          return Inst != FirstInst && (U->getOperandNo() != ChainOperand ||
-                                       !FirstInst->isSameOperationAs(Inst));
+          if (Inst == FirstInst)
+            return false;
+          if (U->getOperandNo() != ChainOperand ||
+              !FirstInst->isSameOperationAs(Inst))
+            return true;
+          // isSameOperationAs does not compare call targets.
+          auto *FirstCB = dyn_cast<CallBase>(FirstInst);
+          return FirstCB && FirstCB->getCalledOperand() !=
+                                cast<CallBase>(Inst)->getCalledOperand();
         }))
       return false;
 
diff --git a/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
index e5244e113f8d1..b758a94e0bba1 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
@@ -463,3 +463,16 @@ define void @and_sext_masks_v16i16(ptr %res, ptr %a, ptr %b) nounwind {
   store <16 x i16> %r, ptr %res
   ret void
 }
+
+define <4 x i64> @or_zext_cmp_masks_v4i64(<4 x i8> %x) {
+; LA32-LABEL: or_zext_cmp_masks_v4i64:
+; LA32:       vext2xv.d.b
+;
+; LA64-LABEL: or_zext_cmp_masks_v4i64:
+; LA64:       vext2xv.d.b
+  %a = icmp ult <4 x i8> %x, splat (i8 1)
+  %b = icmp eq <4 x i8> %x, zeroinitializer
+  %m = or <4 x i1> %a, %b
+  %ext = zext <4 x i1> %m to <4 x i64>
+  ret <4 x i64> %ext
+}
diff --git a/llvm/test/Transforms/VectorCombine/deinterleave-interleave-pairs.ll b/llvm/test/Transforms/VectorCombine/deinterleave-interleave-pairs.ll
index e3c542e900fe0..75388509185f6 100644
--- a/llvm/test/Transforms/VectorCombine/deinterleave-interleave-pairs.ll
+++ b/llvm/test/Transforms/VectorCombine/deinterleave-interleave-pairs.ll
@@ -712,6 +712,41 @@ else:
   ret <vscale x 16 x i16> zeroinitializer
 }
 
+define <4 x i16> @deinterleave2_same_intrinsic_interleave2(<4 x i16> %v) {
+; CHECK-LABEL: define <4 x i16> @deinterleave2_same_intrinsic_interleave2(
+; CHECK-SAME: <4 x i16> [[V:%.*]]) {
+; CHECK-NEXT:    [[R:%.*]] = call <4 x i16> @llvm.smax.v4i16(<4 x i16> [[V]], <4 x i16> splat (i16 3))
+; CHECK-NEXT:    ret <4 x i16> [[R]]
+;
+  %d = call { <2 x i16>, <2 x i16> } @llvm.vector.deinterleave2.v4i16(<4 x i16> %v)
+  %f0 = extractvalue { <2 x i16>, <2 x i16> } %d, 0
+  %f1 = extractvalue { <2 x i16>, <2 x i16> } %d, 1
+  %u0 = call <2 x i16> @llvm.smax.v2i16(<2 x i16> %f0, <2 x i16> splat (i16 3))
+  %u1 = call <2 x i16> @llvm.smax.v2i16(<2 x i16> %f1, <2 x i16> splat (i16 3))
+  %r = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> %u0, <2 x i16> %u1)
+  ret <4 x i16> %r
+}
+
+define <4 x i16> @negative_deinterleave2_different_intrinsics_interleave2(<4 x i16> %v) {
+; CHECK-LABEL: define <4 x i16> @negative_deinterleave2_different_intrinsics_interleave2(
+; CHECK-SAME: <4 x i16> [[V:%.*]]) {
+; CHECK-NEXT:    [[D:%.*]] = call { <2 x i16>, <2 x i16> } @llvm.vector.deinterleave2.v4i16(<4 x i16> [[V]])
+; CHECK-NEXT:    [[F0:%.*]] = extractvalue { <2 x i16>, <2 x i16> } [[D]], 0
+; CHECK-NEXT:    [[F1:%.*]] = extractvalue { <2 x i16>, <2 x i16> } [[D]], 1
+; CHECK-NEXT:    [[U0:%.*]] = call <2 x i16> @llvm.smax.v2i16(<2 x i16> [[F0]], <2 x i16> splat (i16 3))
+; CHECK-NEXT:    [[U1:%.*]] = call <2 x i16> @llvm.smin.v2i16(<2 x i16> [[F1]], <2 x i16> splat (i16 3))
+; CHECK-NEXT:    [[R:%.*]] = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> [[U0]], <2 x i16> [[U1]])
+; CHECK-NEXT:    ret <4 x i16> [[R]]
+;
+  %d = call { <2 x i16>, <2 x i16> } @llvm.vector.deinterleave2.v4i16(<4 x i16> %v)
+  %f0 = extractvalue { <2 x i16>, <2 x i16> } %d, 0
+  %f1 = extractvalue { <2 x i16>, <2 x i16> } %d, 1
+  %u0 = call <2 x i16> @llvm.smax.v2i16(<2 x i16> %f0, <2 x i16> splat (i16 3))
+  %u1 = call <2 x i16> @llvm.smin.v2i16(<2 x i16> %f1, <2 x i16> splat (i16 3))
+  %r = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> %u0, <2 x i16> %u1)
+  ret <4 x i16> %r
+}
+
 !0 = !{!"function_entry_count", i64 1000}
 !1 = !{!"branch_weights", i32 2, i32 3}
 

``````````

</details>


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


More information about the llvm-commits mailing list