[llvm-branch-commits] [llvm] [LoongArch] Mark VPICK_ZEXT_ELT as zero-extending in computeKnownBits (PR #187177)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Mar 20 22:06:26 PDT 2026
https://github.com/heiher updated https://github.com/llvm/llvm-project/pull/187177
>From 52dfba67d5ef7de4c12bb6d68011069e34c58e98 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Tue, 17 Mar 2026 20:53:02 +0800
Subject: [PATCH 1/2] [LoongArch] Mark VPICK_ZEXT_ELT as zero-extending in
computeKnownBits
Teach computeKnownBitsForTargetNode that VPICK_ZEXT_ELT produces a
zero-extended result.
VPICK_ZEXT_ELT extracts a narrower element (e.g. i16) and returns it in a
larger integer type (e.g. i64) with the upper bits guaranteed to be zero.
However, without KnownBits information, LLVM treats the upper bits as
unknown, which inhibits optimizations.
By marking all bits above the source element width as known zero, this
enables DAG combine and other optimizations to eliminate redundant
operations such as AND masks and SIGN_EXTEND_INREG.
For example, this allows patterns like:
(sign_extend_inreg (VPICK_ZEXT_ELT ...), i32)
to be simplified when the sign bit is known to be zero.
---
.../LoongArch/LoongArchISelLowering.cpp | 19 +++++++++
.../Target/LoongArch/LoongArchISelLowering.h | 4 ++
.../LoongArch/lasx/intrinsic-pickve2gr.ll | 21 ++++------
.../LoongArch/lsx/intrinsic-pickve2gr.ll | 40 ++++++-------------
4 files changed, 42 insertions(+), 42 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 9deda5ca564b3..365333adfe898 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -9953,6 +9953,25 @@ unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
}
+void LoongArchTargetLowering::computeKnownBitsForTargetNode(
+ const SDValue Op, KnownBits &Known, const APInt &DemandedElts,
+ const SelectionDAG &DAG, unsigned Depth) const {
+ unsigned BitWidth = Known.getBitWidth();
+ unsigned Opc = Op.getOpcode();
+ Known.resetAll();
+ switch (Opc) {
+ default:
+ break;
+ case LoongArchISD::VPICK_ZEXT_ELT: {
+ EVT VT = cast<VTSDNode>(Op->getOperand(2))->getVT();
+ unsigned VTBits = VT.getScalarSizeInBits();
+ assert(BitWidth >= VTBits && "Unexpected width!");
+ Known.Zero.setBitsFrom(VTBits);
+ break;
+ }
+ }
+}
+
bool LoongArchTargetLowering::SimplifyDemandedBitsForTargetNode(
SDValue Op, const APInt &OriginalDemandedBits,
const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO,
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 1fd9b6b237fe5..797fb5c14dbad 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -156,6 +156,10 @@ class LoongArchTargetLowering : public TargetLowering {
bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const;
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override;
+ void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known,
+ const APInt &DemandedElts,
+ const SelectionDAG &DAG,
+ unsigned Depth) const override;
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits,
const APInt &DemandedElts,
KnownBits &Known,
diff --git a/llvm/test/CodeGen/LoongArch/lasx/intrinsic-pickve2gr.ll b/llvm/test/CodeGen/LoongArch/lasx/intrinsic-pickve2gr.ll
index c1dc65505b45e..a0afc2e15b473 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/intrinsic-pickve2gr.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/intrinsic-pickve2gr.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; 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
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx < %s | FileCheck %s
declare i32 @llvm.loongarch.lasx.xvpickve2gr.w(<8 x i32>, i32)
@@ -27,18 +27,11 @@ entry:
}
define i1 @lasx_xvpickve2gr_wu_cmp(<8 x i32> %va) nounwind {
-; LA32-LABEL: lasx_xvpickve2gr_wu_cmp:
-; LA32: # %bb.0: # %entry
-; LA32-NEXT: xvpickve2gr.wu $a0, $xr0, 1
-; LA32-NEXT: sltui $a0, $a0, 1
-; LA32-NEXT: ret
-;
-; LA64-LABEL: lasx_xvpickve2gr_wu_cmp:
-; LA64: # %bb.0: # %entry
-; LA64-NEXT: xvpickve2gr.wu $a0, $xr0, 1
-; LA64-NEXT: addi.w $a0, $a0, 0
-; LA64-NEXT: sltui $a0, $a0, 1
-; LA64-NEXT: ret
+; CHECK-LABEL: lasx_xvpickve2gr_wu_cmp:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: xvpickve2gr.wu $a0, $xr0, 1
+; CHECK-NEXT: sltui $a0, $a0, 1
+; CHECK-NEXT: ret
entry:
%val = call i32 @llvm.loongarch.lasx.xvpickve2gr.wu(<8 x i32> %va, i32 1)
%tmp = and i32 %val, 4294967295
diff --git a/llvm/test/CodeGen/LoongArch/lsx/intrinsic-pickve2gr.ll b/llvm/test/CodeGen/LoongArch/lsx/intrinsic-pickve2gr.ll
index 82d28c57d7e63..282ba9ccbc889 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/intrinsic-pickve2gr.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/intrinsic-pickve2gr.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; 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
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx < %s | FileCheck %s
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s
declare i32 @llvm.loongarch.lsx.vpickve2gr.b(<16 x i8>, i32)
@@ -54,7 +54,6 @@ define i1 @lsx_vpickve2gr_bu_cmp(<16 x i8> %va) nounwind {
; CHECK-LABEL: lsx_vpickve2gr_bu_cmp:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: vpickve2gr.bu $a0, $vr0, 15
-; CHECK-NEXT: andi $a0, $a0, 255
; CHECK-NEXT: sltui $a0, $a0, 1
; CHECK-NEXT: ret
entry:
@@ -77,19 +76,11 @@ entry:
}
define i1 @lsx_vpickve2gr_hu_cmp(<8 x i16> %va) nounwind {
-; LA32-LABEL: lsx_vpickve2gr_hu_cmp:
-; LA32: # %bb.0: # %entry
-; LA32-NEXT: vpickve2gr.hu $a0, $vr0, 7
-; LA32-NEXT: bstrpick.w $a0, $a0, 15, 0
-; LA32-NEXT: sltui $a0, $a0, 1
-; LA32-NEXT: ret
-;
-; LA64-LABEL: lsx_vpickve2gr_hu_cmp:
-; LA64: # %bb.0: # %entry
-; LA64-NEXT: vpickve2gr.hu $a0, $vr0, 7
-; LA64-NEXT: bstrpick.d $a0, $a0, 15, 0
-; LA64-NEXT: sltui $a0, $a0, 1
-; LA64-NEXT: ret
+; CHECK-LABEL: lsx_vpickve2gr_hu_cmp:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 7
+; CHECK-NEXT: sltui $a0, $a0, 1
+; CHECK-NEXT: ret
entry:
%val = call i32 @llvm.loongarch.lsx.vpickve2gr.hu(<8 x i16> %va, i32 7)
%tmp = and i32 %val, 65535
@@ -110,18 +101,11 @@ entry:
}
define i1 @lsx_vpickve2gr_wu_cmp(<4 x i32> %va) nounwind {
-; LA32-LABEL: lsx_vpickve2gr_wu_cmp:
-; LA32: # %bb.0: # %entry
-; LA32-NEXT: vpickve2gr.wu $a0, $vr0, 3
-; LA32-NEXT: sltui $a0, $a0, 1
-; LA32-NEXT: ret
-;
-; LA64-LABEL: lsx_vpickve2gr_wu_cmp:
-; LA64: # %bb.0: # %entry
-; LA64-NEXT: vpickve2gr.wu $a0, $vr0, 3
-; LA64-NEXT: addi.w $a0, $a0, 0
-; LA64-NEXT: sltui $a0, $a0, 1
-; LA64-NEXT: ret
+; CHECK-LABEL: lsx_vpickve2gr_wu_cmp:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vpickve2gr.wu $a0, $vr0, 3
+; CHECK-NEXT: sltui $a0, $a0, 1
+; CHECK-NEXT: ret
entry:
%val = call i32 @llvm.loongarch.lsx.vpickve2gr.wu(<4 x i32> %va, i32 3)
%tmp = and i32 %val, 4294967295
>From d0d0238e9ce997aca636911938ecbc2759dceb17 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Sat, 21 Mar 2026 13:05:46 +0800
Subject: [PATCH 2/2] Address wanglei's comment
---
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 365333adfe898..791692ace69df 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -9963,6 +9963,7 @@ void LoongArchTargetLowering::computeKnownBitsForTargetNode(
default:
break;
case LoongArchISD::VPICK_ZEXT_ELT: {
+ assert(isa<VTSDNode>(Op->getOperand(2)) && "Unexpected operand!");
EVT VT = cast<VTSDNode>(Op->getOperand(2))->getVT();
unsigned VTBits = VT.getScalarSizeInBits();
assert(BitWidth >= VTBits && "Unexpected width!");
More information about the llvm-branch-commits
mailing list