[llvm-branch-commits] [llvm] [LoongArch] Use unsigned vector extract for zero extension (PR #214120)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Aug 4 19:52:09 PDT 2026
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 <wangrui at loongson.cn>
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:
More information about the llvm-branch-commits
mailing list