[llvm-branch-commits] [llvm] [LoongArch] Add patterns for vector bitwise selection (PR #193753)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Apr 23 06:55:05 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-loongarch
Author: hev (heiher)
<details>
<summary>Changes</summary>
Add instruction selection patterns for VBITSEL_V/XVBITSEL_V and VBITSELI_B/XVBITSELI_B to match the canonical bitwise select idiom:
`(a & b) | (~a & c)`
This enables the backend to generate dedicated bitwise select instructions instead of separate AND/ANDN/OR sequences.
---
Full diff: https://github.com/llvm/llvm-project/pull/193753.diff
4 Files Affected:
- (modified) llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td (+11)
- (modified) llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td (+11)
- (modified) llvm/test/CodeGen/LoongArch/lasx/bitsel.ll (+5-15)
- (modified) llvm/test/CodeGen/LoongArch/lsx/bitsel.ll (+5-15)
``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index b807b5927585b..a0e5834b14398 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -1573,6 +1573,17 @@ def : Pat<(xor (v8i32 LASX256:$xj), (v8i32 (vsplat_uimm_pow2 uimm5:$imm))),
def : Pat<(xor (v4i64 LASX256:$xj), (v4i64 (vsplat_uimm_pow2 uimm6:$imm))),
(XVBITREVI_D LASX256:$xj, uimm6:$imm)>;
+// XVBITSEL_V
+foreach vt = [v32i8, v16i16, v8i32, v4i64] in
+ def : Pat<(vt (or (and LASX256:$va, LASX256:$vk),
+ (loongarch_vandn LASX256:$va, LASX256:$vj))),
+ (vt (XVBITSEL_V LASX256:$vj, LASX256:$vk, LASX256:$va))>;
+
+// XVBITSELI_B
+def : Pat<(v32i8 (or (and LASX256:$vd, (v32i8 (SplatPat_uimm8 uimm8:$imm))),
+ (loongarch_vandn LASX256:$vd, LASX256:$vj))),
+ (XVBITSELI_B LASX256:$vd, LASX256:$vj, uimm8:$imm)>;
+
// Vector bswaps
def : Pat<(bswap (v16i16 LASX256:$xj)), (XVSHUF4I_B LASX256:$xj, 0b10110001)>;
def : Pat<(bswap (v8i32 LASX256:$xj)), (XVSHUF4I_B LASX256:$xj, 0b00011011)>;
diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
index 92d3214363f7b..bfd657bb964d4 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
@@ -1794,6 +1794,17 @@ def : Pat<(xor (v4i32 LSX128:$vj), (v4i32 (vsplat_uimm_pow2 uimm5:$imm))),
def : Pat<(xor (v2i64 LSX128:$vj), (v2i64 (vsplat_uimm_pow2 uimm6:$imm))),
(VBITREVI_D LSX128:$vj, uimm6:$imm)>;
+// VBITSEL_V
+foreach vt = [v16i8, v8i16, v4i32, v2i64] in
+ def : Pat<(vt (or (and LSX128:$va, LSX128:$vk),
+ (loongarch_vandn LSX128:$va, LSX128:$vj))),
+ (vt (VBITSEL_V LSX128:$vj, LSX128:$vk, LSX128:$va))>;
+
+// VBITSELI_B
+def : Pat<(v16i8 (or (and LSX128:$vd, (v16i8 (SplatPat_uimm8 uimm8:$imm))),
+ (loongarch_vandn LSX128:$vd, LSX128:$vj))),
+ (VBITSELI_B LSX128:$vd, LSX128:$vj, uimm8:$imm)>;
+
// Vector bswaps
def : Pat<(bswap (v8i16 LSX128:$vj)), (VSHUF4I_B LSX128:$vj, 0b10110001)>;
def : Pat<(bswap (v4i32 LSX128:$vj)), (VSHUF4I_B LSX128:$vj, 0b00011011)>;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/bitsel.ll b/llvm/test/CodeGen/LoongArch/lasx/bitsel.ll
index c1a67a2dcf1dd..54157284aa152 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/bitsel.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/bitsel.ll
@@ -5,9 +5,7 @@
define <32 x i8> @bitsel_v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %c) nounwind {
; CHECK-LABEL: bitsel_v32i8:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvand.v $xr1, $xr2, $xr1
-; CHECK-NEXT: xvandn.v $xr0, $xr2, $xr0
-; CHECK-NEXT: xvor.v $xr0, $xr1, $xr0
+; CHECK-NEXT: xvbitsel.v $xr0, $xr0, $xr1, $xr2
; CHECK-NEXT: ret
entry:
%0 = and <32 x i8> %c, %b
@@ -20,9 +18,7 @@ entry:
define <16 x i16> @bitsel_v16i16(<16 x i16> %a, <16 x i16> %b, <16 x i16> %c) nounwind {
; CHECK-LABEL: bitsel_v16i16:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvand.v $xr1, $xr2, $xr1
-; CHECK-NEXT: xvandn.v $xr0, $xr2, $xr0
-; CHECK-NEXT: xvor.v $xr0, $xr1, $xr0
+; CHECK-NEXT: xvbitsel.v $xr0, $xr0, $xr1, $xr2
; CHECK-NEXT: ret
entry:
%0 = and <16 x i16> %c, %b
@@ -35,9 +31,7 @@ entry:
define <8 x i32> @bitsel_v8i32(<8 x i32> %a, <8 x i32> %b, <8 x i32> %c) nounwind {
; CHECK-LABEL: bitsel_v8i32:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvand.v $xr1, $xr2, $xr1
-; CHECK-NEXT: xvandn.v $xr0, $xr2, $xr0
-; CHECK-NEXT: xvor.v $xr0, $xr1, $xr0
+; CHECK-NEXT: xvbitsel.v $xr0, $xr0, $xr1, $xr2
; CHECK-NEXT: ret
entry:
%0 = and <8 x i32> %c, %b
@@ -50,9 +44,7 @@ entry:
define <4 x i64> @bitsel_v4i64(<4 x i64> %a, <4 x i64> %b, <4 x i64> %c) nounwind {
; CHECK-LABEL: bitsel_v4i64:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvand.v $xr1, $xr2, $xr1
-; CHECK-NEXT: xvandn.v $xr0, $xr2, $xr0
-; CHECK-NEXT: xvor.v $xr0, $xr1, $xr0
+; CHECK-NEXT: xvbitsel.v $xr0, $xr0, $xr1, $xr2
; CHECK-NEXT: ret
entry:
%0 = and <4 x i64> %c, %b
@@ -65,9 +57,7 @@ entry:
define <32 x i8> @bitsel_v32i8_1(<32 x i8> %a, <32 x i8> %b) nounwind {
; CHECK-LABEL: bitsel_v32i8_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvandi.b $xr2, $xr0, 1
-; CHECK-NEXT: xvandn.v $xr0, $xr0, $xr1
-; CHECK-NEXT: xvor.v $xr0, $xr2, $xr0
+; CHECK-NEXT: xvbitseli.b $xr0, $xr1, 1
; CHECK-NEXT: ret
entry:
%0 = and <32 x i8> %a, splat (i8 1)
diff --git a/llvm/test/CodeGen/LoongArch/lsx/bitsel.ll b/llvm/test/CodeGen/LoongArch/lsx/bitsel.ll
index eb39012eeaa81..fd5bdcb17030a 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/bitsel.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/bitsel.ll
@@ -5,9 +5,7 @@
define <16 x i8> @bitsel_v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) nounwind {
; CHECK-LABEL: bitsel_v16i8:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vand.v $vr1, $vr2, $vr1
-; CHECK-NEXT: vandn.v $vr0, $vr2, $vr0
-; CHECK-NEXT: vor.v $vr0, $vr1, $vr0
+; CHECK-NEXT: vbitsel.v $vr0, $vr0, $vr1, $vr2
; CHECK-NEXT: ret
entry:
%0 = and <16 x i8> %c, %b
@@ -20,9 +18,7 @@ entry:
define <8 x i16> @bitsel_v8i16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) nounwind {
; CHECK-LABEL: bitsel_v8i16:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vand.v $vr1, $vr2, $vr1
-; CHECK-NEXT: vandn.v $vr0, $vr2, $vr0
-; CHECK-NEXT: vor.v $vr0, $vr1, $vr0
+; CHECK-NEXT: vbitsel.v $vr0, $vr0, $vr1, $vr2
; CHECK-NEXT: ret
entry:
%0 = and <8 x i16> %c, %b
@@ -35,9 +31,7 @@ entry:
define <4 x i32> @bitsel_v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) nounwind {
; CHECK-LABEL: bitsel_v4i32:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vand.v $vr1, $vr2, $vr1
-; CHECK-NEXT: vandn.v $vr0, $vr2, $vr0
-; CHECK-NEXT: vor.v $vr0, $vr1, $vr0
+; CHECK-NEXT: vbitsel.v $vr0, $vr0, $vr1, $vr2
; CHECK-NEXT: ret
entry:
%0 = and <4 x i32> %c, %b
@@ -50,9 +44,7 @@ entry:
define <2 x i64> @bitsel_v2i64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) nounwind {
; CHECK-LABEL: bitsel_v2i64:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vand.v $vr1, $vr2, $vr1
-; CHECK-NEXT: vandn.v $vr0, $vr2, $vr0
-; CHECK-NEXT: vor.v $vr0, $vr1, $vr0
+; CHECK-NEXT: vbitsel.v $vr0, $vr0, $vr1, $vr2
; CHECK-NEXT: ret
entry:
%0 = and <2 x i64> %c, %b
@@ -65,9 +57,7 @@ entry:
define <16 x i8> @bitsel_v16i8_1(<16 x i8> %a, <16 x i8> %b) nounwind {
; CHECK-LABEL: bitsel_v16i8_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vandi.b $vr2, $vr0, 1
-; CHECK-NEXT: vandn.v $vr0, $vr0, $vr1
-; CHECK-NEXT: vor.v $vr0, $vr2, $vr0
+; CHECK-NEXT: vbitseli.b $vr0, $vr1, 1
; CHECK-NEXT: ret
entry:
%0 = and <16 x i8> %a, splat (i8 1)
``````````
</details>
https://github.com/llvm/llvm-project/pull/193753
More information about the llvm-branch-commits
mailing list