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
