[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