https://github.com/heiher created https://github.com/llvm/llvm-project/pull/214120
Add patterns to select VPICKVE2GR_BU/HU and [X]VPICKVE2GR_WU for vector extraction followed by zero extension, eliminating redundant masking instructions. >From 15af95a889271800e76356e6076fdbf45483852a Mon Sep 17 00:00:00 2001 From: WANG Rui <[email protected]> Date: Wed, 5 Aug 2026 10:32:28 +0800 Subject: [PATCH] [LoongArch] Use unsigned vector extract for zero extension Add patterns to select VPICKVE2GR_BU/HU and [X]VPICKVE2GR_WU for vector extraction followed by zero extension, eliminating redundant masking instructions. --- .../LoongArch/LoongArchLASXInstrInfo.td | 28 ++++++++++ .../Target/LoongArch/LoongArchLSXInstrInfo.td | 13 +++++ .../lasx/ir-instruction/extractelement.ll | 54 ++++++------------- .../lsx/ir-instruction/extractelement.ll | 27 +++------- 4 files changed, 65 insertions(+), 57 deletions(-) diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td index e75bfc690fe53..4fa625e78dea5 100644 --- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td @@ -2106,6 +2106,34 @@ def : Pat<(loongarch_movfr2gr_s_la64 (f32 (vector_extract v8f32:$xj, uimm3:$imm) def : Pat<(i64 (bitconvert (f64 (vector_extract v4f64:$xj, uimm2:$imm)))), (XVPICKVE2GR_D v4f64:$xj, uimm2:$imm)>; +// Vector extraction with zero extension and constant index. +foreach imm = 16...31 in { + defvar Imm = !and(imm, 15); + def : Pat<(GRLenVT (and (vector_extract v32i8:$xj, imm), 255)), + (VPICKVE2GR_BU (EXTRACT_SUBREG (XVPERMI_D v32i8:$xj, 14), sub_128), + Imm)>; +} +foreach imm = 8...15 in { + defvar Imm = !and(imm, 7); + def : Pat<(GRLenVT (and (vector_extract v16i16:$xj, imm), 65535)), + (VPICKVE2GR_HU (EXTRACT_SUBREG (XVPERMI_D v16i16:$xj, 14), sub_128), + Imm)>; + def : Pat<(GRLenVT (loongarch_bstrpick (vector_extract v16i16:$xj, imm), + (GRLenVT 15), (GRLenVT 0))), + (VPICKVE2GR_HU (EXTRACT_SUBREG (XVPERMI_D v16i16:$xj, 14), sub_128), + Imm)>; +} +def : Pat<(GRLenVT (and (vector_extract v32i8:$xj, uimm4:$imm), 255)), + (VPICKVE2GR_BU (EXTRACT_SUBREG v32i8:$xj, sub_128), uimm4:$imm)>; +def : Pat<(GRLenVT (and (vector_extract v16i16:$xj, uimm3:$imm), 65535)), + (VPICKVE2GR_HU (EXTRACT_SUBREG v16i16:$xj, sub_128), uimm3:$imm)>; +def : Pat<(GRLenVT (loongarch_bstrpick (vector_extract v16i16:$xj, uimm3:$imm), + (GRLenVT 15), (GRLenVT 0))), + (VPICKVE2GR_HU (EXTRACT_SUBREG v16i16:$xj, sub_128), uimm3:$imm)>; +def : Pat<(GRLenVT (loongarch_bstrpick (vector_extract v8i32:$xj, uimm3:$imm), + (GRLenVT 31), (GRLenVT 0))), + (XVPICKVE2GR_WU v8i32:$xj, uimm3:$imm)>; + // Vector extraction with constant index. foreach imm = 16...31 in { defvar Imm = !and(imm, 15); diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td index 657b7294a6080..351f0a4cf86d2 100644 --- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td @@ -2328,6 +2328,19 @@ def : Pat<(loongarch_movfr2gr_s_la64 (f32 (vector_extract v4f32:$vj, uimm2:$imm) def : Pat<(i64 (bitconvert (f64 (vector_extract v2f64:$vj, uimm1:$imm)))), (VPICKVE2GR_D v2f64:$vj, uimm1:$imm)>; + +// Vector extraction with zero extension and constant index. +def : Pat<(GRLenVT (and (vector_extract v16i8:$vj, uimm4:$imm), 255)), + (VPICKVE2GR_BU v16i8:$vj, uimm4:$imm)>; +def : Pat<(GRLenVT (and (vector_extract v8i16:$vj, uimm3:$imm), 65535)), + (VPICKVE2GR_HU v8i16:$vj, uimm3:$imm)>; +def : Pat<(GRLenVT (loongarch_bstrpick (vector_extract v8i16:$vj, uimm3:$imm), + (GRLenVT 15), (GRLenVT 0))), + (VPICKVE2GR_HU v8i16:$vj, uimm3:$imm)>; +def : Pat<(GRLenVT (loongarch_bstrpick (vector_extract v4i32:$vj, uimm2:$imm), + (GRLenVT 31), (GRLenVT 0))), + (VPICKVE2GR_WU v4i32:$vj, uimm2:$imm)>; + // Vector extraction with constant index. def : Pat<(GRLenVT (vector_extract v16i8:$vj, uimm4:$imm)), (VPICKVE2GR_B v16i8:$vj, uimm4:$imm)>; diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/extractelement.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/extractelement.ll index 826c4fe0a315d..afcbad0b2a0e5 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/extractelement.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/extractelement.ll @@ -247,8 +247,7 @@ define void @vextract_32xi8_zext(ptr %src, ptr %dst) nounwind { ; CHECK-LABEL: vextract_32xi8_zext: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 0 -; CHECK-NEXT: andi $a0, $a0, 255 +; CHECK-NEXT: vpickve2gr.bu $a0, $vr0, 0 ; CHECK-NEXT: st.w $a0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -264,8 +263,7 @@ define void @vextract_32xi8_zext_hi(ptr %src, ptr %dst) nounwind { ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 0 -; CHECK-NEXT: andi $a0, $a0, 255 +; CHECK-NEXT: vpickve2gr.bu $a0, $vr0, 0 ; CHECK-NEXT: st.w $a0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -277,21 +275,12 @@ entry: } define void @vextract_16xi16_zext(ptr %src, ptr %dst) nounwind { -; LA32-LABEL: vextract_16xi16_zext: -; LA32: # %bb.0: # %entry -; LA32-NEXT: xvld $xr0, $a0, 0 -; LA32-NEXT: vpickve2gr.h $a0, $vr0, 0 -; LA32-NEXT: bstrpick.w $a0, $a0, 15, 0 -; LA32-NEXT: st.w $a0, $a1, 0 -; LA32-NEXT: ret -; -; LA64-LABEL: vextract_16xi16_zext: -; LA64: # %bb.0: # %entry -; LA64-NEXT: xvld $xr0, $a0, 0 -; LA64-NEXT: vpickve2gr.h $a0, $vr0, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 15, 0 -; LA64-NEXT: st.w $a0, $a1, 0 -; LA64-NEXT: ret +; CHECK-LABEL: vextract_16xi16_zext: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xvld $xr0, $a0, 0 +; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0 +; CHECK-NEXT: st.w $a0, $a1, 0 +; CHECK-NEXT: ret entry: %0 = load volatile <16 x i16>, ptr %src %1 = extractelement <16 x i16> %0, i64 0 @@ -301,23 +290,13 @@ entry: } define void @vextract_16xi16_zext_hi(ptr %src, ptr %dst) nounwind { -; LA32-LABEL: vextract_16xi16_zext_hi: -; LA32: # %bb.0: # %entry -; LA32-NEXT: xvld $xr0, $a0, 0 -; LA32-NEXT: xvpermi.d $xr0, $xr0, 14 -; LA32-NEXT: vpickve2gr.h $a0, $vr0, 0 -; LA32-NEXT: bstrpick.w $a0, $a0, 15, 0 -; LA32-NEXT: st.w $a0, $a1, 0 -; LA32-NEXT: ret -; -; LA64-LABEL: vextract_16xi16_zext_hi: -; LA64: # %bb.0: # %entry -; LA64-NEXT: xvld $xr0, $a0, 0 -; LA64-NEXT: xvpermi.d $xr0, $xr0, 14 -; LA64-NEXT: vpickve2gr.h $a0, $vr0, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 15, 0 -; LA64-NEXT: st.w $a0, $a1, 0 -; LA64-NEXT: ret +; CHECK-LABEL: vextract_16xi16_zext_hi: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xvld $xr0, $a0, 0 +; CHECK-NEXT: xvpermi.d $xr0, $xr0, 14 +; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0 +; CHECK-NEXT: st.w $a0, $a1, 0 +; CHECK-NEXT: ret entry: %0 = load volatile <16 x i16>, ptr %src %1 = extractelement <16 x i16> %0, i64 8 @@ -338,8 +317,7 @@ define void @vextract_8xi32_zext(ptr %src, ptr %dst) nounwind { ; LA64-LABEL: vextract_8xi32_zext: ; LA64: # %bb.0: # %entry ; LA64-NEXT: xvld $xr0, $a0, 0 -; LA64-NEXT: xvpickve2gr.w $a0, $xr0, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: xvpickve2gr.wu $a0, $xr0, 0 ; LA64-NEXT: st.d $a0, $a1, 0 ; LA64-NEXT: ret entry: diff --git a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/extractelement.ll b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/extractelement.ll index 75ef121ed64e2..b4d1e9061fd01 100644 --- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/extractelement.ll +++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/extractelement.ll @@ -237,8 +237,7 @@ define void @extract_16xi8_zext(ptr %src, ptr %dst) nounwind { ; CHECK-LABEL: extract_16xi8_zext: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vld $vr0, $a0, 0 -; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 0 -; CHECK-NEXT: andi $a0, $a0, 255 +; CHECK-NEXT: vpickve2gr.bu $a0, $vr0, 0 ; CHECK-NEXT: st.w $a0, $a1, 0 ; CHECK-NEXT: ret entry: @@ -250,21 +249,12 @@ entry: } define void @extract_8xi16_zext(ptr %src, ptr %dst) nounwind { -; LA32-LABEL: extract_8xi16_zext: -; LA32: # %bb.0: # %entry -; LA32-NEXT: vld $vr0, $a0, 0 -; LA32-NEXT: vpickve2gr.h $a0, $vr0, 0 -; LA32-NEXT: bstrpick.w $a0, $a0, 15, 0 -; LA32-NEXT: st.w $a0, $a1, 0 -; LA32-NEXT: ret -; -; LA64-LABEL: extract_8xi16_zext: -; LA64: # %bb.0: # %entry -; LA64-NEXT: vld $vr0, $a0, 0 -; LA64-NEXT: vpickve2gr.h $a0, $vr0, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 15, 0 -; LA64-NEXT: st.w $a0, $a1, 0 -; LA64-NEXT: ret +; CHECK-LABEL: extract_8xi16_zext: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vld $vr0, $a0, 0 +; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0 +; CHECK-NEXT: st.w $a0, $a1, 0 +; CHECK-NEXT: ret entry: %0 = load volatile <8 x i16>, ptr %src %1 = extractelement <8 x i16> %0, i64 0 @@ -285,8 +275,7 @@ define void @extract_4xi32_zext(ptr %src, ptr %dst) nounwind { ; LA64-LABEL: extract_4xi32_zext: ; LA64: # %bb.0: # %entry ; LA64-NEXT: vld $vr0, $a0, 0 -; LA64-NEXT: vpickve2gr.w $a0, $vr0, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: vpickve2gr.wu $a0, $vr0, 0 ; LA64-NEXT: st.d $a0, $a1, 0 ; LA64-NEXT: ret entry: _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
