[llvm] [RISCV] Add vector hasAndNot to enable optimizations (PR #132438)

Piotr Fusik via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 25 09:30:50 PDT 2025


https://github.com/pfusik updated https://github.com/llvm/llvm-project/pull/132438

>From e4f013cf1a45acc091e0fe9f05a972396d1e0370 Mon Sep 17 00:00:00 2001
From: Piotr Fusik <p.fusik at samsung.com>
Date: Fri, 21 Mar 2025 18:14:26 +0100
Subject: [PATCH 1/4] [RISCV] Add vector hasAndNot to enable optimizations

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 10 +++++++++-
 llvm/lib/Target/RISCV/RISCVISelLowering.h   |  1 +
 llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll |  6 +++---
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index f09b8e42b9005..752fed3d479a2 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -2052,7 +2052,6 @@ bool RISCVTargetLowering::isMaskAndCmp0FoldingBeneficial(
 bool RISCVTargetLowering::hasAndNotCompare(SDValue Y) const {
   EVT VT = Y.getValueType();
 
-  // FIXME: Support vectors once we have tests.
   if (VT.isVector())
     return false;
 
@@ -2060,6 +2059,15 @@ bool RISCVTargetLowering::hasAndNotCompare(SDValue Y) const {
          (!isa<ConstantSDNode>(Y) || cast<ConstantSDNode>(Y)->isOpaque());
 }
 
+bool RISCVTargetLowering::hasAndNot(SDValue Y) const {
+  EVT VT = Y.getValueType();
+
+  if (!VT.isVector())
+    return hasAndNotCompare(Y);
+
+  return Subtarget.hasStdExtZvkb();
+}
+
 bool RISCVTargetLowering::hasBitTest(SDValue X, SDValue Y) const {
   // Zbs provides BEXT[_I], which can be used with SEQZ/SNEZ as a bit test.
   if (Subtarget.hasStdExtZbs())
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 4072f8ea2fc67..f4d6cd86397a4 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -535,6 +535,7 @@ class RISCVTargetLowering : public TargetLowering {
   bool isCheapToSpeculateCtlz(Type *Ty) const override;
   bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override;
   bool hasAndNotCompare(SDValue Y) const override;
+  bool hasAndNot(SDValue Y) const override;
   bool hasBitTest(SDValue X, SDValue Y) const override;
   bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(
       SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y,
diff --git a/llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll
index 5c24de2fd5601..319cd94c651aa 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll
@@ -2580,9 +2580,9 @@ define <vscale x 1 x i8> @not_signbit_mask_nxv1i8(<vscale x 1 x i8> %a, <vscale
 ; CHECK-ZVKB-LABEL: not_signbit_mask_nxv1i8:
 ; CHECK-ZVKB:       # %bb.0:
 ; CHECK-ZVKB-NEXT:    vsetvli a0, zero, e8, mf8, ta, ma
-; CHECK-ZVKB-NEXT:    vmsgt.vi v0, v8, -1
-; CHECK-ZVKB-NEXT:    vmv.v.i v8, 0
-; CHECK-ZVKB-NEXT:    vmerge.vvm v8, v8, v9, v0
+; CHECK-ZVKB-NEXT:    vsra.vi v8, v8, 7
+; CHECK-ZVKB-NEXT:    vnot.v v8, v8
+; CHECK-ZVKB-NEXT:    vand.vv v8, v8, v9
 ; CHECK-ZVKB-NEXT:    ret
   %cond = icmp sgt <vscale x 1 x i8> %a, splat (i8 -1)
   %r = select <vscale x 1 x i1> %cond, <vscale x 1 x i8> %b, <vscale x 1 x i8> zeroinitializer

>From 12376ba0ea301ccab045a352c4ad4dfc8b34a8e8 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 24 Mar 2025 15:57:50 +0100
Subject: [PATCH 2/4] [RISCV] Match VANDN ignoring XOR constant bits above SEW

---
 llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td  | 9 ++++++---
 llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll | 3 +--
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td
index fcbb2dbc76a37..904ce1b616c2d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td
@@ -603,13 +603,16 @@ multiclass VPatUnarySDNode_V<SDPatternOperator op, string instruction_name,
 // This should match the logic in RISCVDAGToDAGISel::selectVSplat
 def riscv_splat_vector : PatFrag<(ops node:$rs1),
                                  (riscv_vmv_v_x_vl undef, node:$rs1, srcvalue)>;
-def riscv_vnot : PatFrag<(ops node:$rs1), (xor node:$rs1,
-                                               (riscv_splat_vector -1))>;
+def allonessew8  : ImmLeaf<XLenVT, "return SignExtend64<8>(Imm) == -1LL;">;
+def allonessew16 : ImmLeaf<XLenVT, "return SignExtend64<16>(Imm) == -1LL;">;
+def allonessew32 : ImmLeaf<XLenVT, "return SignExtend64<32>(Imm) == -1LL;">;
+def allonessew64 : ImmLeaf<XLenVT, "return Imm == -1LL;">;
 
 foreach vti = AllIntegerVectors in {
   let Predicates = !listconcat([HasStdExtZvkb],
                                GetVTypePredicates<vti>.Predicates) in {
-    def : Pat<(vti.Vector (and (riscv_vnot vti.RegClass:$rs1),
+    def : Pat<(vti.Vector (and (xor vti.RegClass:$rs1,
+                                    (riscv_splat_vector !cast<ImmLeaf>("allonessew"#vti.SEW))),
                                vti.RegClass:$rs2)),
               (!cast<Instruction>("PseudoVANDN_VV_"#vti.LMul.MX)
                  (vti.Vector (IMPLICIT_DEF)),
diff --git a/llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll
index 319cd94c651aa..aef46e1f5cf1b 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll
@@ -2581,8 +2581,7 @@ define <vscale x 1 x i8> @not_signbit_mask_nxv1i8(<vscale x 1 x i8> %a, <vscale
 ; CHECK-ZVKB:       # %bb.0:
 ; CHECK-ZVKB-NEXT:    vsetvli a0, zero, e8, mf8, ta, ma
 ; CHECK-ZVKB-NEXT:    vsra.vi v8, v8, 7
-; CHECK-ZVKB-NEXT:    vnot.v v8, v8
-; CHECK-ZVKB-NEXT:    vand.vv v8, v8, v9
+; CHECK-ZVKB-NEXT:    vandn.vv v8, v9, v8
 ; CHECK-ZVKB-NEXT:    ret
   %cond = icmp sgt <vscale x 1 x i8> %a, splat (i8 -1)
   %r = select <vscale x 1 x i1> %cond, <vscale x 1 x i8> %b, <vscale x 1 x i8> zeroinitializer

>From 1b6cd9935eb20e4d174da68a94571e4cacd45e93 Mon Sep 17 00:00:00 2001
From: Piotr Fusik <p.fusik at samsung.com>
Date: Tue, 25 Mar 2025 17:22:24 +0100
Subject: [PATCH 3/4] [RISCV][test] Add fixed vectors tests for hasAndNot

---
 .../CodeGen/RISCV/rvv/fixed-vectors-vandn.ll  | 88 +++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll

diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll
new file mode 100644
index 0000000000000..78df3f066f70e
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll
@@ -0,0 +1,88 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv32 -mattr=+v,+zvkb -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK-ZVKB
+; RUN: llc -mtriple=riscv64 -mattr=+v,+zvkb -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK-ZVKB
+
+define <8 x i8> @not_signbit_mask_v8i8(<8 x i8> %a, <8 x i8> %b) {
+; CHECK-LABEL: not_signbit_mask_v8i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 8, e8, mf2, ta, ma
+; CHECK-NEXT:    vmsgt.vi v0, v8, -1
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vmerge.vvm v8, v8, v9, v0
+; CHECK-NEXT:    ret
+;
+; CHECK-ZVKB-LABEL: not_signbit_mask_v8i8:
+; CHECK-ZVKB:       # %bb.0:
+; CHECK-ZVKB-NEXT:    vsetivli zero, 8, e8, mf2, ta, ma
+; CHECK-ZVKB-NEXT:    vsra.vi v8, v8, 7
+; CHECK-ZVKB-NEXT:    vnot.v v8, v8
+; CHECK-ZVKB-NEXT:    vand.vv v8, v8, v9
+; CHECK-ZVKB-NEXT:    ret
+  %cond = icmp sgt <8 x i8> %a, splat (i8 -1)
+  %r = select <8 x i1> %cond, <8 x i8> %b, <8 x i8> zeroinitializer
+  ret <8 x i8> %r
+}
+
+define <4 x i16> @not_signbit_mask_v4i16(<4 x i16> %a, <4 x i16> %b) {
+; CHECK-LABEL: not_signbit_mask_v4i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 4, e16, mf2, ta, ma
+; CHECK-NEXT:    vmsgt.vi v0, v8, -1
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vmerge.vvm v8, v8, v9, v0
+; CHECK-NEXT:    ret
+;
+; CHECK-ZVKB-LABEL: not_signbit_mask_v4i16:
+; CHECK-ZVKB:       # %bb.0:
+; CHECK-ZVKB-NEXT:    vsetivli zero, 4, e16, mf2, ta, ma
+; CHECK-ZVKB-NEXT:    vsra.vi v8, v8, 15
+; CHECK-ZVKB-NEXT:    vnot.v v8, v8
+; CHECK-ZVKB-NEXT:    vand.vv v8, v8, v9
+; CHECK-ZVKB-NEXT:    ret
+  %cond = icmp sgt <4 x i16> %a, splat (i16 -1)
+  %r = select <4 x i1> %cond, <4 x i16> %b, <4 x i16> zeroinitializer
+  ret <4 x i16> %r
+}
+
+define <2 x i32> @not_signbit_mask_v2i32(<2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: not_signbit_mask_v2i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 2, e32, mf2, ta, ma
+; CHECK-NEXT:    vmsgt.vi v0, v8, -1
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vmerge.vvm v8, v8, v9, v0
+; CHECK-NEXT:    ret
+;
+; CHECK-ZVKB-LABEL: not_signbit_mask_v2i32:
+; CHECK-ZVKB:       # %bb.0:
+; CHECK-ZVKB-NEXT:    vsetivli zero, 2, e32, mf2, ta, ma
+; CHECK-ZVKB-NEXT:    vsra.vi v8, v8, 31
+; CHECK-ZVKB-NEXT:    vandn.vv v8, v9, v8
+; CHECK-ZVKB-NEXT:    ret
+  %cond = icmp sgt <2 x i32> %a, splat (i32 -1)
+  %r = select <2 x i1> %cond, <2 x i32> %b, <2 x i32> zeroinitializer
+  ret <2 x i32> %r
+}
+
+define <2 x i64> @not_signbit_mask_v2i64(<2 x i64> %a, <2 x i64> %b) {
+; CHECK-LABEL: not_signbit_mask_v2i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
+; CHECK-NEXT:    vmsgt.vi v0, v8, -1
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vmerge.vvm v8, v8, v9, v0
+; CHECK-NEXT:    ret
+;
+; CHECK-ZVKB-LABEL: not_signbit_mask_v2i64:
+; CHECK-ZVKB:       # %bb.0:
+; CHECK-ZVKB-NEXT:    li a0, 63
+; CHECK-ZVKB-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
+; CHECK-ZVKB-NEXT:    vsra.vx v8, v8, a0
+; CHECK-ZVKB-NEXT:    vandn.vv v8, v9, v8
+; CHECK-ZVKB-NEXT:    ret
+  %cond = icmp sgt <2 x i64> %a, splat (i64 -1)
+  %r = select <2 x i1> %cond, <2 x i64> %b, <2 x i64> zeroinitializer
+  ret <2 x i64> %r
+}

>From 5be683a4659ff9cf29f05d3b2b9833af1c8bf04e Mon Sep 17 00:00:00 2001
From: Piotr Fusik <p.fusik at samsung.com>
Date: Tue, 25 Mar 2025 17:22:36 +0100
Subject: [PATCH 4/4] [RISCV] VL pattern for VANDN ignoring XOR constant bits
 above SEW

---
 llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td         | 2 +-
 llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll | 6 ++----
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td
index 904ce1b616c2d..4147c97a7a23a 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td
@@ -737,7 +737,7 @@ foreach vti = AllIntegerVectors in {
                                GetVTypePredicates<vti>.Predicates) in {
     def : Pat<(vti.Vector (riscv_and_vl (riscv_xor_vl
                                            (vti.Vector vti.RegClass:$rs1),
-                                           (riscv_splat_vector -1),
+                                           (riscv_splat_vector !cast<ImmLeaf>("allonessew"#vti.SEW)),
                                            (vti.Vector vti.RegClass:$passthru),
                                            (vti.Mask VMV0:$vm),
                                            VLOpFrag),
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll
index 78df3f066f70e..ae7f8ed78aa06 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vandn.ll
@@ -17,8 +17,7 @@ define <8 x i8> @not_signbit_mask_v8i8(<8 x i8> %a, <8 x i8> %b) {
 ; CHECK-ZVKB:       # %bb.0:
 ; CHECK-ZVKB-NEXT:    vsetivli zero, 8, e8, mf2, ta, ma
 ; CHECK-ZVKB-NEXT:    vsra.vi v8, v8, 7
-; CHECK-ZVKB-NEXT:    vnot.v v8, v8
-; CHECK-ZVKB-NEXT:    vand.vv v8, v8, v9
+; CHECK-ZVKB-NEXT:    vandn.vv v8, v9, v8
 ; CHECK-ZVKB-NEXT:    ret
   %cond = icmp sgt <8 x i8> %a, splat (i8 -1)
   %r = select <8 x i1> %cond, <8 x i8> %b, <8 x i8> zeroinitializer
@@ -38,8 +37,7 @@ define <4 x i16> @not_signbit_mask_v4i16(<4 x i16> %a, <4 x i16> %b) {
 ; CHECK-ZVKB:       # %bb.0:
 ; CHECK-ZVKB-NEXT:    vsetivli zero, 4, e16, mf2, ta, ma
 ; CHECK-ZVKB-NEXT:    vsra.vi v8, v8, 15
-; CHECK-ZVKB-NEXT:    vnot.v v8, v8
-; CHECK-ZVKB-NEXT:    vand.vv v8, v8, v9
+; CHECK-ZVKB-NEXT:    vandn.vv v8, v9, v8
 ; CHECK-ZVKB-NEXT:    ret
   %cond = icmp sgt <4 x i16> %a, splat (i16 -1)
   %r = select <4 x i1> %cond, <4 x i16> %b, <4 x i16> zeroinitializer



More information about the llvm-commits mailing list