https://github.com/heiher updated https://github.com/llvm/llvm-project/pull/207316
>From 9473b4e3d6c298d0729f438c3a7ee509665d64a4 Mon Sep 17 00:00:00 2001 From: WANG Rui <[email protected]> Date: Thu, 2 Jul 2026 16:17:59 +0800 Subject: [PATCH 1/2] [LoongArch] Add DAG combines for vector widening extends Lower: ``` SEXT/ZEXT(High-Half-128-Bit-Lanes(vec)) ``` to: ``` LSX: VEXTH.H.B, VEXTH.W.H, VEXTH.D.W VEXTH.HU.BU, VEXTH.WU.HU, VEXTH.DU.WU LASX: XVEXTH.H.B, XVEXTH.W.H, XVEXTH.D.W XVEXTH.HU.BU, XVEXTH.WU.HU, XVEXTH.DU.WU ``` --- .../LoongArch/LoongArchISelLowering.cpp | 35 +++-- .../LoongArch/LoongArchLASXInstrInfo.td | 24 ++++ .../Target/LoongArch/LoongArchLSXInstrInfo.td | 29 ++++ llvm/test/CodeGen/LoongArch/lasx/xvexth.ll | 128 +----------------- llvm/test/CodeGen/LoongArch/lsx/vexth.ll | 42 ++---- 5 files changed, 94 insertions(+), 164 deletions(-) diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 9dc6d23711ec1..03460d3f67a2d 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -521,13 +521,13 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, setTargetDAGCombine(ISD::FP_TO_SINT); setTargetDAGCombine(ISD::FP_TO_UINT); setTargetDAGCombine(ISD::UINT_TO_FP); + setTargetDAGCombine(ISD::ZERO_EXTEND); + setTargetDAGCombine(ISD::SIGN_EXTEND); } // Set DAG combine for 'LASX' feature. if (Subtarget.hasExtLASX()) { setTargetDAGCombine(ISD::ANY_EXTEND); - setTargetDAGCombine(ISD::ZERO_EXTEND); - setTargetDAGCombine(ISD::SIGN_EXTEND); setTargetDAGCombine(ISD::CONCAT_VECTORS); } @@ -6363,15 +6363,17 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, DAG.getConstant(lsb, DL, GRLenVT)); } -// Return the original source vector if N consists of the low half +// Return the original source vector if N consists of the half // of each 128-bit lane. -static SDValue matchLowHalfOf128BitLanes(SDValue N) { +static SDValue matchHalfOf128BitLanes(SDValue N, bool isLow) { N = peekThroughBitcasts(N); EVT DstVT = N.getValueType(); if (!DstVT.isVector()) return SDValue(); + unsigned NumElts = DstVT.getVectorNumElements(); + // LSX canonical form: if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR) { SDValue Src = N.getOperand(0); @@ -6379,11 +6381,11 @@ static SDValue matchLowHalfOf128BitLanes(SDValue N) { if (!SrcVT.isVector() || !SrcVT.is128BitVector()) return SDValue(); - if (N.getConstantOperandVal(1) != 0) - return SDValue(); if (SrcVT.getSizeInBits() != DstVT.getSizeInBits() * 2) return SDValue(); - if (SrcVT.getVectorNumElements() != DstVT.getVectorNumElements() * 2) + if (SrcVT.getVectorNumElements() != NumElts * 2) + return SDValue(); + if (N.getConstantOperandVal(1) != (isLow ? 0 : NumElts)) return SDValue(); return Src; @@ -6394,7 +6396,6 @@ static SDValue matchLowHalfOf128BitLanes(SDValue N) { if (!BV) return SDValue(); - unsigned NumElts = DstVT.getVectorNumElements(); if (NumElts % 2 != 0) return SDValue(); @@ -6418,18 +6419,20 @@ static SDValue matchLowHalfOf128BitLanes(SDValue N) { if (!SrcVT.isVector()) return SDValue(); + if (!SrcVT.is256BitVector()) + return SDValue(); if (SrcVT.getSizeInBits() != DstVT.getSizeInBits() * 2) return SDValue(); if (SrcVT.getVectorNumElements() != NumElts * 2) return SDValue(); - if (!SrcVT.is256BitVector()) - return SDValue(); } else if (ThisSrc != Src) { return SDValue(); } unsigned Half = NumElts / 2; unsigned ExpectedIdx = (I < Half) ? I : (I + Half); + ExpectedIdx += isLow ? 0 : Half; + if (CI->getZExtValue() != ExpectedIdx) return SDValue(); } @@ -6463,7 +6466,7 @@ static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, if (!LHS.hasOneUse()) return SDValue(); - SDValue Vec = matchLowHalfOf128BitLanes(LHS.getOperand(0)); + SDValue Vec = matchHalfOf128BitLanes(LHS.getOperand(0), true); if (!Vec) return SDValue(); @@ -8407,10 +8410,18 @@ static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, EVT VT = N->getValueType(0); SDLoc DL(N); - if (VT.isVector()) + if (VT.isVector()) { if (SDValue R = PromoteMaskArithmetic(SDValue(N, 0), DL, DAG, Subtarget)) return R; + if (SDValue R = matchHalfOf128BitLanes(N->getOperand(0), false)) { + if (N->getOpcode() == ISD::SIGN_EXTEND) + return DAG.getNode(LoongArchISD::VEXTH, DL, VT, R); + else if (N->getOpcode() == ISD::ZERO_EXTEND) + return DAG.getNode(LoongArchISD::VEXTH_U, DL, VT, R); + } + } + return SDValue(); } diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td index 21d937d5b4275..7c261bbf8f015 100644 --- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td @@ -1135,6 +1135,24 @@ multiclass PatXrF<SDPatternOperator OpNode, string Inst> { (!cast<LAInst>(Inst#"_D") LASX256:$xj)>; } +multiclass PatXrW<SDPatternOperator OpNode, string Inst> { + def : Pat<(v16i16 (OpNode(v32i8 LASX256:$vj))), + (!cast<LAInst>(Inst#"_H_B") LASX256:$vj)>; + def : Pat<(v8i32 (OpNode(v16i16 LASX256:$vj))), + (!cast<LAInst>(Inst#"_W_H") LASX256:$vj)>; + def : Pat<(v4i64 (OpNode(v8i32 LASX256:$vj))), + (!cast<LAInst>(Inst#"_D_W") LASX256:$vj)>; +} + +multiclass PatXrWU<SDPatternOperator OpNode, string Inst> { + def : Pat<(v16i16 (OpNode(v32i8 LASX256:$vj))), + (!cast<LAInst>(Inst#"_HU_BU") LASX256:$vj)>; + def : Pat<(v8i32 (OpNode(v16i16 LASX256:$vj))), + (!cast<LAInst>(Inst#"_WU_HU") LASX256:$vj)>; + def : Pat<(v4i64 (OpNode(v8i32 LASX256:$vj))), + (!cast<LAInst>(Inst#"_DU_WU") LASX256:$vj)>; +} + multiclass PatXrXr<SDPatternOperator OpNode, string Inst> { def : Pat<(OpNode (v32i8 LASX256:$xj), (v32i8 LASX256:$xk)), (!cast<LAInst>(Inst#"_B") LASX256:$xj, LASX256:$xk)>; @@ -1522,6 +1540,12 @@ defm : PatXrUimmW<loongarch_vsllwil, "XVSLLWIL">; // XVSLLWIL_{HU_BU/WU_HU/DU_WU} defm : PatXrUimmWU<loongarch_vsllwil_u, "XVSLLWIL">; +// VEXTH_{H_B/W_H/D_W} +defm : PatXrW<loongarch_vexth, "XVEXTH">; + +// VEXTH_{HU_BU/WU_HU/DU_WU} +defm : PatXrWU<loongarch_vexth_u, "XVEXTH">; + // XVCLO_{B/H/W/D} def : Pat<(ctlz (vnot v32i8:$xj)), (XVCLO_B v32i8:$xj)>; def : Pat<(ctlz (vnot v16i16:$xj)), (XVCLO_H v16i16:$xj)>; diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td index d545976d58712..c953b5c4b7623 100644 --- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td @@ -27,6 +27,7 @@ def SDT_LoongArchV2RUimm : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, GRLenVT>]>; +def SDT_LoongArchVEW : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>]>; def SDT_LoongArchVHW : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1, 2>]>; def SDT_LoongArchVSW : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisVT<2, GRLenVT>]>; def SDT_LoongArchVreplgr2vr : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVec<0>, SDTCisInt<1>]>; @@ -101,6 +102,10 @@ def loongarch_vhaddw_u : SDNode<"LoongArchISD::VHADDW_U", SDT_LoongArchVHW>; def loongarch_vhsubw : SDNode<"LoongArchISD::VHSUBW", SDT_LoongArchVHW>; def loongarch_vhsubw_u : SDNode<"LoongArchISD::VHSUBW_U", SDT_LoongArchVHW>; +// Vector Extend with Widening +def loongarch_vexth : SDNode<"LoongArchISD::VEXTH", SDT_LoongArchVEW>; +def loongarch_vexth_u : SDNode<"LoongArchISD::VEXTH_U", SDT_LoongArchVEW>; + // Scalar load broadcast to vector def loongarch_vldrepl : SDNode<"LoongArchISD::VLDREPL", @@ -1381,6 +1386,24 @@ multiclass PatVrF<SDPatternOperator OpNode, string Inst> { (!cast<LAInst>(Inst#"_D") LSX128:$vj)>; } +multiclass PatVrW<SDPatternOperator OpNode, string Inst> { + def : Pat<(v8i16 (OpNode(v16i8 LSX128:$vj))), + (!cast<LAInst>(Inst#"_H_B") LSX128:$vj)>; + def : Pat<(v4i32 (OpNode(v8i16 LSX128:$vj))), + (!cast<LAInst>(Inst#"_W_H") LSX128:$vj)>; + def : Pat<(v2i64 (OpNode(v4i32 LSX128:$vj))), + (!cast<LAInst>(Inst#"_D_W") LSX128:$vj)>; +} + +multiclass PatVrWU<SDPatternOperator OpNode, string Inst> { + def : Pat<(v8i16 (OpNode(v16i8 LSX128:$vj))), + (!cast<LAInst>(Inst#"_HU_BU") LSX128:$vj)>; + def : Pat<(v4i32 (OpNode(v8i16 LSX128:$vj))), + (!cast<LAInst>(Inst#"_WU_HU") LSX128:$vj)>; + def : Pat<(v2i64 (OpNode(v4i32 LSX128:$vj))), + (!cast<LAInst>(Inst#"_DU_WU") LSX128:$vj)>; +} + multiclass PatVrVr<SDPatternOperator OpNode, string Inst> { def : Pat<(OpNode (v16i8 LSX128:$vj), (v16i8 LSX128:$vk)), (!cast<LAInst>(Inst#"_B") LSX128:$vj, LSX128:$vk)>; @@ -1782,6 +1805,12 @@ defm : PatVrUimmW<loongarch_vsllwil, "VSLLWIL">; // VSLLWIL_{HU_BU/WU_HU/DU_WU} defm : PatVrUimmWU<loongarch_vsllwil_u, "VSLLWIL">; +// VEXTH_{H_B/W_H/D_W} +defm : PatVrW<loongarch_vexth, "VEXTH">; + +// VEXTH_{HU_BU/WU_HU/DU_WU} +defm : PatVrWU<loongarch_vexth_u, "VEXTH">; + // VCLO_{B/H/W/D} def : Pat<(ctlz (vnot v16i8:$vj)), (VCLO_B v16i8:$vj)>; def : Pat<(ctlz (vnot v8i16:$vj)), (VCLO_H v8i16:$vj)>; diff --git a/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll b/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll index 17a2913c8bc5f..2b72f299a0719 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll @@ -6,40 +6,7 @@ define void @xvexth_h_b(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_h_b: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 8 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 9 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 1 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 10 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 2 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 11 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 3 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 12 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 4 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 13 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 5 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 14 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 6 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 15 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 7 -; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 8 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 8 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 9 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 9 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 10 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 10 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 11 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 11 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 12 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 12 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 13 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 13 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 14 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 14 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 15 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 15 -; CHECK-NEXT: vext2xv.h.b $xr0, $xr1 +; CHECK-NEXT: xvexth.h.b $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -102,24 +69,7 @@ define void @xvexth_w_h(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_w_h: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 4 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 0 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 5 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 1 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 6 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 2 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 7 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 3 -; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 4 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 4 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 5 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 5 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 6 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 6 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 7 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 7 -; CHECK-NEXT: vext2xv.w.h $xr0, $xr1 +; CHECK-NEXT: xvexth.w.h $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -166,15 +116,7 @@ define void @xvexth_d_w(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_d_w: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 2 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 0 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 3 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 1 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 6 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 2 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 7 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 3 -; CHECK-NEXT: vext2xv.d.w $xr0, $xr1 +; CHECK-NEXT: xvexth.d.w $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -212,40 +154,7 @@ define void @xvexth_hu_bu(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_hu_bu: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 8 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 9 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 1 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 10 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 2 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 11 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 3 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 12 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 4 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 13 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 5 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 14 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 6 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 15 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 7 -; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 8 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 8 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 9 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 9 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 10 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 10 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 11 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 11 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 12 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 12 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 13 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 13 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 14 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 14 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 15 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 15 -; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr1 +; CHECK-NEXT: xvexth.hu.bu $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -308,24 +217,7 @@ define void @xvexth_wu_hu(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_wu_hu: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 4 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 0 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 5 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 1 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 6 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 2 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 7 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 3 -; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 4 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 4 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 5 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 5 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 6 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 6 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 7 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 7 -; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr1 +; CHECK-NEXT: xvexth.wu.hu $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -372,15 +264,7 @@ define void @xvexth_du_wu(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_du_wu: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 2 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 0 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 3 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 1 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 6 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 2 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 7 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 3 -; CHECK-NEXT: vext2xv.du.wu $xr0, $xr1 +; CHECK-NEXT: xvexth.du.wu $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/LoongArch/lsx/vexth.ll b/llvm/test/CodeGen/LoongArch/lsx/vexth.ll index 92ff7df93a4f2..d85c4eb7fa1ac 100644 --- a/llvm/test/CodeGen/LoongArch/lsx/vexth.ll +++ b/llvm/test/CodeGen/LoongArch/lsx/vexth.ll @@ -6,9 +6,7 @@ define void @vexth_h_b(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_h_b: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vbsrl.v $vr0, $vr0, 8 -; CHECK-NEXT: vslti.b $vr1, $vr0, 0 -; CHECK-NEXT: vilvl.b $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.h.b $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -24,9 +22,7 @@ define void @vexth_h_b_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_h_b_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vbsrl.v $vr0, $vr0, 8 -; CHECK-NEXT: vslti.b $vr1, $vr0, 0 -; CHECK-NEXT: vilvl.b $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.h.b $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -42,9 +38,7 @@ define void @vexth_w_h(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_w_h: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vbsrl.v $vr0, $vr0, 8 -; CHECK-NEXT: vslti.h $vr1, $vr0, 0 -; CHECK-NEXT: vilvl.h $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.w.h $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -59,9 +53,7 @@ define void @vexth_w_h_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_w_h_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vbsrl.v $vr0, $vr0, 8 -; CHECK-NEXT: vslti.h $vr1, $vr0, 0 -; CHECK-NEXT: vilvl.h $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.w.h $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -76,9 +68,7 @@ define void @vexth_d_w(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_d_w: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vshuf4i.w $vr0, $vr0, 14 -; CHECK-NEXT: vslti.w $vr1, $vr0, 0 -; CHECK-NEXT: vilvl.w $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.d.w $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -93,9 +83,7 @@ define void @vexth_d_w_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_d_w_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vshuf4i.w $vr0, $vr0, 14 -; CHECK-NEXT: vslti.w $vr1, $vr0, 0 -; CHECK-NEXT: vilvl.w $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.d.w $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -110,8 +98,7 @@ define void @vexth_hu_bu(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_hu_bu: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vrepli.b $vr1, 0 -; CHECK-NEXT: vilvh.b $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.hu.bu $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -127,8 +114,7 @@ define void @vexth_hu_bu_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_hu_bu_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vrepli.b $vr1, 0 -; CHECK-NEXT: vilvh.b $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.hu.bu $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -144,8 +130,7 @@ define void @vexth_wu_hu(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_wu_hu: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vrepli.b $vr1, 0 -; CHECK-NEXT: vilvh.h $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.wu.hu $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -160,8 +145,7 @@ define void @vexth_wu_hu_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_wu_hu_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vrepli.b $vr1, 0 -; CHECK-NEXT: vilvh.h $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.wu.hu $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -176,8 +160,7 @@ define void @vexth_du_wu(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_du_wu: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vrepli.b $vr1, 0 -; CHECK-NEXT: vilvh.w $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.du.wu $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -192,8 +175,7 @@ define void @vexth_du_wu_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: vexth_du_wu_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vrepli.b $vr1, 0 -; CHECK-NEXT: vilvh.w $vr0, $vr1, $vr0 +; CHECK-NEXT: vexth.du.wu $vr0, $vr0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: ret entry: >From 4cfb8c140cb9cf29950f9fd2dd55c93816e344ab Mon Sep 17 00:00:00 2001 From: WANG Rui <[email protected]> Date: Tue, 7 Jul 2026 12:56:24 +0800 Subject: [PATCH 2/2] Address wanglei's comments --- .../LoongArch/LoongArchISelLowering.cpp | 8 +- llvm/test/CodeGen/LoongArch/lasx/xvexth.ll | 112 +----------------- 2 files changed, 11 insertions(+), 109 deletions(-) diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 03460d3f67a2d..59f4b0b683214 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -6404,6 +6404,8 @@ static SDValue matchHalfOf128BitLanes(SDValue N, bool isLow) { for (unsigned I = 0; I != NumElts; ++I) { SDValue Elt = BV->getOperand(I); + if (Elt.isUndef()) + continue; if (Elt.getOpcode() != ISD::EXTRACT_VECTOR_ELT) return SDValue(); @@ -6466,7 +6468,7 @@ static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, if (!LHS.hasOneUse()) return SDValue(); - SDValue Vec = matchHalfOf128BitLanes(LHS.getOperand(0), true); + SDValue Vec = matchHalfOf128BitLanes(LHS.getOperand(0), /*isLow=*/true); if (!Vec) return SDValue(); @@ -8414,10 +8416,10 @@ static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, if (SDValue R = PromoteMaskArithmetic(SDValue(N, 0), DL, DAG, Subtarget)) return R; - if (SDValue R = matchHalfOf128BitLanes(N->getOperand(0), false)) { + if (SDValue R = matchHalfOf128BitLanes(N->getOperand(0), /*isLow=*/false)) { if (N->getOpcode() == ISD::SIGN_EXTEND) return DAG.getNode(LoongArchISD::VEXTH, DL, VT, R); - else if (N->getOpcode() == ISD::ZERO_EXTEND) + if (N->getOpcode() == ISD::ZERO_EXTEND) return DAG.getNode(LoongArchISD::VEXTH_U, DL, VT, R); } } diff --git a/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll b/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll index 2b72f299a0719..db3a4c9c66368 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/xvexth.ll @@ -23,36 +23,7 @@ define void @xvexth_h_b_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_h_b_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 8 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 9 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 1 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 10 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 2 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 11 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 3 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 12 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 4 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 13 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 5 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 14 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 6 -; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 8 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 8 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 9 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 9 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 10 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 10 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 11 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 11 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 12 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 12 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 13 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 13 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 14 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 14 -; CHECK-NEXT: vext2xv.h.b $xr0, $xr1 +; CHECK-NEXT: xvexth.h.b $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -85,22 +56,7 @@ define void @xvexth_w_h_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_w_h_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 4 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 0 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 5 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 1 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 6 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 2 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 7 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 3 -; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 4 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 4 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 5 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 5 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 6 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 6 -; CHECK-NEXT: vext2xv.w.h $xr0, $xr1 +; CHECK-NEXT: xvexth.w.h $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -132,13 +88,7 @@ define void @xvexth_d_w_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_d_w_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 2 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 0 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 3 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 1 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 6 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 2 -; CHECK-NEXT: vext2xv.d.w $xr0, $xr1 +; CHECK-NEXT: xvexth.d.w $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -171,36 +121,7 @@ define void @xvexth_hu_bu_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_hu_bu_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 8 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 9 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 1 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 10 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 2 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 11 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 3 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 12 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 4 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 13 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 5 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 14 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 6 -; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 8 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 8 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 9 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 9 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 10 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 10 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 11 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 11 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 12 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 12 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 13 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 13 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 14 -; CHECK-NEXT: vinsgr2vr.b $vr1, $a0, 14 -; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr1 +; CHECK-NEXT: xvexth.hu.bu $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -233,22 +154,7 @@ define void @xvexth_wu_hu_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_wu_hu_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 4 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 0 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 5 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 1 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 6 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 2 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 7 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 3 -; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 4 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 4 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 5 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 5 -; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 6 -; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 6 -; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr1 +; CHECK-NEXT: xvexth.wu.hu $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -280,13 +186,7 @@ define void @xvexth_du_wu_poison(ptr %a, ptr %r) nounwind { ; CHECK-LABEL: xvexth_du_wu_poison: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 2 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 0 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 3 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 1 -; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 6 -; CHECK-NEXT: vinsgr2vr.w $vr1, $a0, 2 -; CHECK-NEXT: vext2xv.du.wu $xr0, $xr1 +; CHECK-NEXT: xvexth.du.wu $xr0, $xr0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: ret entry: _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
