[llvm] 4a75259 - [LoongArch] Fix invalid VEXTH combines for unsupported type extensions (#209725)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 16 19:23:56 PDT 2026
Author: hev
Date: 2026-07-17T10:23:52+08:00
New Revision: 4a75259134c72d8be7fa3ea36c9dc7bfc02640ac
URL: https://github.com/llvm/llvm-project/commit/4a75259134c72d8be7fa3ea36c9dc7bfc02640ac
DIFF: https://github.com/llvm/llvm-project/commit/4a75259134c72d8be7fa3ea36c9dc7bfc02640ac.diff
LOG: [LoongArch] Fix invalid VEXTH combines for unsupported type extensions (#209725)
`performEXTENDCombine` could form `VEXTH`/`VEXTH_U` nodes for
unsupported type combinations, such as extending `v8i8` to `v8i32` or
`v2i64` to `v2i128`. These illegal nodes would later reach instruction
selection and trigger backend failures:
* `Cannot select: LoongArchISD::VEXTH`
* `Don't know how to legalize this operation`
Prevent these combines from firing by verifying that the destination
type is legal and has exactly twice the total bit width of the source
before forming a `VEXTH`/`VEXTH_U` node.
Apply the same checks to `performSHLCombine` for consistency.
Fixes
https://github.com/llvm/llvm-project/pull/207316#issuecomment-4978234865
Fixes
https://github.com/llvm/llvm-project/pull/207316#issuecomment-4979233899
Added:
llvm/test/CodeGen/LoongArch/lasx/issue207316.ll
Modified:
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
llvm/test/CodeGen/LoongArch/lasx/xvexth.ll
llvm/test/CodeGen/LoongArch/lsx/vexth.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 4c5bb28a5e42f..d6189ff6b988d 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -6504,9 +6504,6 @@ static SDValue matchHalfOf128BitLanes(SDValue N, bool isLow) {
static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const LoongArchSubtarget &Subtarget) {
- if (!Subtarget.hasExtLSX())
- return SDValue();
-
assert(N->getOpcode() == ISD::SHL && "Unexpected opcode");
EVT VT = N->getValueType(0);
@@ -6527,6 +6524,10 @@ static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
if (!LHS.hasOneUse())
return SDValue();
+ if (!DAG.getTargetLoweringInfo().isTypeLegal(VT) ||
+ N->getValueSizeInBits(0) != LHS->getOperand(0).getValueSizeInBits() * 2)
+ return SDValue();
+
SDValue Vec = matchHalfOf128BitLanes(LHS.getOperand(0), /*isLow=*/true);
if (!Vec)
return SDValue();
@@ -6534,16 +6535,6 @@ static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
EVT SrcVT = Vec.getValueType();
EVT SrcEltVT = SrcVT.getVectorElementType();
EVT DstEltVT = VT.getVectorElementType();
-
- if (!SrcVT.isVector() || !VT.isVector())
- return SDValue();
- if (SrcVT.getSizeInBits() != VT.getSizeInBits())
- return SDValue();
- if (DstEltVT.getSizeInBits() != SrcEltVT.getSizeInBits() * 2)
- return SDValue();
- if (!SrcEltVT.isInteger() || SrcEltVT.getSizeInBits() > 32)
- return SDValue();
-
APInt Imm;
if (!isConstantSplatVector(RHS, Imm, DstEltVT.getSizeInBits()))
return SDValue();
@@ -8512,6 +8503,10 @@ static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG,
if (SDValue R = PromoteMaskArithmetic(SDValue(N, 0), DL, DAG, Subtarget))
return R;
+ if (!DAG.getTargetLoweringInfo().isTypeLegal(VT) ||
+ N->getValueSizeInBits(0) != N->getOperand(0).getValueSizeInBits() * 2)
+ return SDValue();
+
if (SDValue R = matchHalfOf128BitLanes(N->getOperand(0), /*isLow=*/false)) {
if (N->getOpcode() == ISD::SIGN_EXTEND)
return DAG.getNode(LoongArchISD::VEXTH, DL, VT, R);
diff --git a/llvm/test/CodeGen/LoongArch/lasx/issue207316.ll b/llvm/test/CodeGen/LoongArch/lasx/issue207316.ll
new file mode 100644
index 0000000000000..1012918abde30
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/issue207316.ll
@@ -0,0 +1,18 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx < %s | FileCheck %s
+
+;; https://github.com/llvm/llvm-project/pull/207316#issuecomment-4978234865
+define void @exth_wu_bu() nounwind {
+; CHECK-LABEL: exth_wu_bu:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: xvrepli.b $xr0, 0
+; CHECK-NEXT: xvst $xr0, $zero, 0
+; CHECK-NEXT: ret
+entry:
+ %0 = shufflevector <16 x i8> zeroinitializer, <16 x i8> zeroinitializer,
+ <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %1 = zext <8 x i8> %0 to <8 x i32>
+ store <8 x i32> %1, ptr null
+ ret void
+}
diff --git a/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll b/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll
index db3a4c9c66368..e8d0cd4e2a297 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx < %s | FileCheck %s
-; RUN: llc --mtriple=loongarch64 --mattr=+lasx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx < %s | FileCheck %s --check-prefixes=CHECK,LA64
define void @xvexth_h_b(ptr %a, ptr %r) nounwind {
; CHECK-LABEL: xvexth_h_b:
@@ -100,6 +100,47 @@ entry:
ret void
}
+define void @xvexth_q_d(ptr %a, ptr %r) nounwind {
+; LA32-LABEL: xvexth_q_d:
+; LA32: # %bb.0: # %entry
+; LA32-NEXT: xvld $xr0, $a0, 0
+; LA32-NEXT: xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT: xvpickve2gr.w $a2, $xr0, 6
+; LA32-NEXT: xvpickve2gr.w $a3, $xr0, 7
+; LA32-NEXT: xvpickve2gr.w $a4, $xr0, 3
+; LA32-NEXT: srai.w $a5, $a4, 31
+; LA32-NEXT: srai.w $a6, $a3, 31
+; LA32-NEXT: st.w $a3, $a1, 20
+; LA32-NEXT: st.w $a2, $a1, 16
+; LA32-NEXT: st.w $a4, $a1, 4
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: st.w $a6, $a1, 28
+; LA32-NEXT: st.w $a6, $a1, 24
+; LA32-NEXT: st.w $a5, $a1, 12
+; LA32-NEXT: st.w $a5, $a1, 8
+; LA32-NEXT: ret
+;
+; LA64-LABEL: xvexth_q_d:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: xvld $xr0, $a0, 0
+; LA64-NEXT: xvpickve2gr.d $a0, $xr0, 3
+; LA64-NEXT: xvpickve2gr.d $a2, $xr0, 1
+; LA64-NEXT: srai.d $a2, $a2, 63
+; LA64-NEXT: srai.d $a0, $a0, 63
+; LA64-NEXT: xvstelm.d $xr0, $a1, 16, 3
+; LA64-NEXT: xvstelm.d $xr0, $a1, 0, 1
+; LA64-NEXT: st.d $a0, $a1, 24
+; LA64-NEXT: st.d $a2, $a1, 8
+; LA64-NEXT: ret
+entry:
+ %0 = load <4 x i64>, ptr %a
+ %1 = shufflevector <4 x i64> %0, <4 x i64> poison,
+ <2 x i32> <i32 1, i32 3>
+ %2 = sext <2 x i64> %1 to <2 x i128>
+ store <2 x i128> %2, ptr %r
+ ret void
+}
+
define void @xvexth_hu_bu(ptr %a, ptr %r) nounwind {
; CHECK-LABEL: xvexth_hu_bu:
; CHECK: # %bb.0: # %entry
@@ -182,6 +223,41 @@ entry:
ret void
}
+define void @xvexth_qu_du(ptr %a, ptr %r) nounwind {
+; LA32-LABEL: xvexth_qu_du:
+; LA32: # %bb.0: # %entry
+; LA32-NEXT: xvld $xr0, $a0, 0
+; LA32-NEXT: xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT: xvpickve2gr.w $a2, $xr0, 3
+; LA32-NEXT: xvpickve2gr.w $a3, $xr0, 6
+; LA32-NEXT: xvpickve2gr.w $a4, $xr0, 7
+; LA32-NEXT: st.w $zero, $a1, 28
+; LA32-NEXT: st.w $zero, $a1, 24
+; LA32-NEXT: st.w $zero, $a1, 12
+; LA32-NEXT: st.w $zero, $a1, 8
+; LA32-NEXT: st.w $a4, $a1, 20
+; LA32-NEXT: st.w $a3, $a1, 16
+; LA32-NEXT: st.w $a2, $a1, 4
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: xvexth_qu_du:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: xvld $xr0, $a0, 0
+; LA64-NEXT: st.d $zero, $a1, 24
+; LA64-NEXT: xvstelm.d $xr0, $a1, 16, 3
+; LA64-NEXT: st.d $zero, $a1, 8
+; LA64-NEXT: xvstelm.d $xr0, $a1, 0, 1
+; LA64-NEXT: ret
+entry:
+ %0 = load <4 x i64>, ptr %a
+ %1 = shufflevector <4 x i64> %0, <4 x i64> poison,
+ <2 x i32> <i32 1, i32 3>
+ %2 = zext <2 x i64> %1 to <2 x i128>
+ store <2 x i128> %2, ptr %r
+ ret void
+}
+
define void @xvexth_du_wu_poison(ptr %a, ptr %r) nounwind {
; CHECK-LABEL: xvexth_du_wu_poison:
; CHECK: # %bb.0: # %entry
diff --git a/llvm/test/CodeGen/LoongArch/lsx/vexth.ll b/llvm/test/CodeGen/LoongArch/lsx/vexth.ll
index d85c4eb7fa1ac..b8e87a0ccd058 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/vexth.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/vexth.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx < %s | FileCheck %s
-; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s --check-prefixes=CHECK,LA64
define void @vexth_h_b(ptr %a, ptr %r) nounwind {
; CHECK-LABEL: vexth_h_b:
@@ -94,6 +94,34 @@ entry:
ret void
}
+define void @vexth_q_d(ptr %a, ptr %r) nounwind {
+; LA32-LABEL: vexth_q_d:
+; LA32: # %bb.0: # %entry
+; LA32-NEXT: vld $vr0, $a0, 0
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 2
+; LA32-NEXT: vpickve2gr.w $a2, $vr0, 3
+; LA32-NEXT: srai.w $a3, $a2, 31
+; LA32-NEXT: st.w $a2, $a1, 4
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: st.w $a3, $a1, 12
+; LA32-NEXT: st.w $a3, $a1, 8
+; LA32-NEXT: ret
+;
+; LA64-LABEL: vexth_q_d:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: ld.d $a0, $a0, 8
+; LA64-NEXT: srai.d $a2, $a0, 63
+; LA64-NEXT: st.d $a0, $a1, 0
+; LA64-NEXT: st.d $a2, $a1, 8
+; LA64-NEXT: ret
+entry:
+ %0 = load <2 x i64>, ptr %a
+ %1 = shufflevector <2 x i64> %0, <2 x i64> poison, <1 x i32> <i32 1>
+ %2 = sext <1 x i64> %1 to <1 x i128>
+ store <1 x i128> %2, ptr %r
+ ret void
+}
+
define void @vexth_hu_bu(ptr %a, ptr %r) nounwind {
; CHECK-LABEL: vexth_hu_bu:
; CHECK: # %bb.0: # %entry
@@ -185,3 +213,29 @@ entry:
store <2 x i64> %2, ptr %r
ret void
}
+
+define void @vexth_qu_du(ptr %a, ptr %r) nounwind {
+; LA32-LABEL: vexth_qu_du:
+; LA32: # %bb.0: # %entry
+; LA32-NEXT: vld $vr0, $a0, 0
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 2
+; LA32-NEXT: vpickve2gr.w $a2, $vr0, 3
+; LA32-NEXT: st.w $zero, $a1, 12
+; LA32-NEXT: st.w $zero, $a1, 8
+; LA32-NEXT: st.w $a2, $a1, 4
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: vexth_qu_du:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: ld.d $a0, $a0, 8
+; LA64-NEXT: st.d $zero, $a1, 8
+; LA64-NEXT: st.d $a0, $a1, 0
+; LA64-NEXT: ret
+entry:
+ %0 = load <2 x i64>, ptr %a
+ %1 = shufflevector <2 x i64> %0, <2 x i64> poison, <1 x i32> <i32 1>
+ %2 = zext <1 x i64> %1 to <1 x i128>
+ store <1 x i128> %2, ptr %r
+ ret void
+}
More information about the llvm-commits
mailing list