Author: hev
Date: 2026-07-17T02:34:20Z
New Revision: 66ba3bdaa25418fed2e74cd39576f236498bf289

URL: 
https://github.com/llvm/llvm-project/commit/66ba3bdaa25418fed2e74cd39576f236498bf289
DIFF: 
https://github.com/llvm/llvm-project/commit/66ba3bdaa25418fed2e74cd39576f236498bf289.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

(cherry picked from commit 4a75259134c72d8be7fa3ea36c9dc7bfc02640ac)

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
+}


        
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to