[llvm] [RISCV] DAG combine special case for AND/OR immediately (PR #79101)

Liao Chunyu via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 23 20:19:27 PST 2024


https://github.com/ChunyuLiao updated https://github.com/llvm/llvm-project/pull/79101

>From 4bc96cb1bb6f5bba814766440d2c00a1da8e73e3 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Wed, 24 Jan 2024 12:12:23 +0800
Subject: [PATCH] [RISCV]DAG combine special vp.select to logic

vp.select Cond, 0, F, EVL --> and (not Cond), F, EVL
vp.select Cond, T, 0, EVL --> and Cond, T, EVL
vp.select Cond, 1, F, EVL --> or Cond, F, EVL
vp.select Cond, T, 1, EVL --> or (not Cond), T, EVL
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 31 ++++++++++-
 llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll   | 62 +++++++++++++++++++++
 2 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 76e8d21b818b25..f630fefed4ec5d 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1402,7 +1402,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
                          ISD::SHL, ISD::STORE, ISD::SPLAT_VECTOR,
                          ISD::BUILD_VECTOR, ISD::CONCAT_VECTORS,
                          ISD::EXPERIMENTAL_VP_REVERSE, ISD::MUL,
-                         ISD::INSERT_VECTOR_ELT});
+                         ISD::INSERT_VECTOR_ELT, ISD::VP_SELECT});
   if (Subtarget.hasVendorXTHeadMemPair())
     setTargetDAGCombine({ISD::LOAD, ISD::STORE});
   if (Subtarget.useRVVForFixedLengthVectors())
@@ -15556,6 +15556,35 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
     }
     break;
   }
+  case ISD::VP_SELECT: {
+    EVT VT = N->getOperand(1).getValueType();
+    if (VT.isSimple() && VT.isScalableVector() &&
+        VT.getVectorElementType() == MVT::i1) {
+      SDValue N0 = N->getOperand(0);
+      SDValue N1 = N->getOperand(1);
+      SDValue N2 = N->getOperand(2);
+      SDValue VL = N->getOperand(3);
+      SDLoc DL(N);
+      // vp.select Cond, 0, F, EVL --> and (not Cond), F, EVL
+      // vp.select Cond, T, 0, EVL --> and Cond, T, EVL
+      // vp.select Cond, 1, F, EVL --> or Cond, F, EVL
+      // vp.select Cond, T, 1, EVL --> or (not Cond), T, EVL
+      if (isNullOrNullSplat(N1)) {
+        SDValue Not = DAG.getNode(RISCVISD::VMXOR_VL, DL, VT, N0,
+                                  DAG.getAllOnesConstant(DL, VT), VL);
+        return DAG.getNode(RISCVISD::VMAND_VL, DL, VT, Not, N2, VL);
+      } else if (isNullOrNullSplat(N2)) {
+        return DAG.getNode(RISCVISD::VMAND_VL, DL, VT, N0, N1, VL);
+      } else if (isOneOrOneSplat(N1)) {
+        return DAG.getNode(RISCVISD::VMOR_VL, DL, VT, N0, N1, VL);
+      } else if (isOneOrOneSplat(N2)) {
+        SDValue Not = DAG.getNode(RISCVISD::VMXOR_VL, DL, VT, N0,
+                                  DAG.getAllOnesConstant(DL, VT), VL);
+        return DAG.getNode(RISCVISD::VMOR_VL, DL, VT, Not, N1, VL);
+      }
+    }
+    return SDValue();
+  }
   case ISD::VP_GATHER: {
     const auto *VPGN = dyn_cast<VPGatherSDNode>(N);
     SDValue Index = VPGN->getIndex();
diff --git a/llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll b/llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll
index 9e7df5eab8dda9..9b21266058e2ce 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll
@@ -745,3 +745,65 @@ define <vscale x 16 x double> @select_nxv16f64(<vscale x 16 x i1> %a, <vscale x
   %v = call <vscale x 16 x double> @llvm.vp.select.nxv16f64(<vscale x 16 x i1> %a, <vscale x 16 x double> %b, <vscale x 16 x double> %c, i32 %evl)
   ret <vscale x 16 x double> %v
 }
+
+define <vscale x 2 x i1> @select_zero(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, <vscale x 2 x i1> %m, i32 zeroext %evl) {
+; CHECK-LABEL: select_zero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli zero, a0, e8, mf4, ta, ma
+; CHECK-NEXT:    vmand.mm v0, v8, v0
+; CHECK-NEXT:    ret
+  %a = call <vscale x 2 x i1> @llvm.vp.select.nxv2i1(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, <vscale x 2 x i1> zeroinitializer, i32 %evl)
+  ret <vscale x 2 x i1> %a
+}
+
+define <vscale x 2 x i1> @select_one(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, <vscale x 2 x i1> %m, i32 zeroext %evl) {
+; CHECK-LABEL: select_one:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli zero, a0, e8, mf4, ta, ma
+; CHECK-NEXT:    vmorn.mm v0, v8, v0
+; CHECK-NEXT:    ret
+  %a = call <vscale x 2 x i1> @llvm.vp.select.nxv2i1(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, <vscale x 2 x i1> shufflevector (<vscale x 2 x i1> insertelement (<vscale x 2 x i1> undef, i1 true, i32 0), <vscale x 2 x i1> undef, <vscale x 2 x i32> zeroinitializer), i32 %evl)
+  ret <vscale x 2 x i1> %a
+}
+
+define <vscale x 2 x i1> @select_x_zero(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, i32 zeroext %evl) {
+; CHECK-LABEL: select_x_zero:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli zero, a0, e8, mf4, ta, ma
+; CHECK-NEXT:    vmand.mm v0, v0, v8
+; CHECK-NEXT:    ret
+  %a = call <vscale x 2 x i1> @llvm.vp.select.nxv2i1(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, <vscale x 2 x i1> zeroinitializer, i32 %evl)
+  ret <vscale x 2 x i1> %a
+}
+
+define <vscale x 2 x i1> @select_x_one(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, i32 zeroext %evl) {
+; CHECK-LABEL: select_x_one:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli zero, a0, e8, mf4, ta, ma
+; CHECK-NEXT:    vmorn.mm v0, v8, v0
+; CHECK-NEXT:    ret
+  %a = call <vscale x 2 x i1> @llvm.vp.select.nxv2i1(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, <vscale x 2 x i1> shufflevector (<vscale x 2 x i1> insertelement (<vscale x 2 x i1> undef, i1 true, i32 0), <vscale x 2 x i1> undef, <vscale x 2 x i32> zeroinitializer), i32 %evl)
+  ret <vscale x 2 x i1> %a
+}
+
+define <vscale x 2 x i1> @select_zero_x(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, i32 zeroext %evl) {
+; CHECK-LABEL: select_zero_x:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli zero, a0, e8, mf4, ta, ma
+; CHECK-NEXT:    vmandn.mm v0, v8, v0
+; CHECK-NEXT:    ret
+  %a = call <vscale x 2 x i1> @llvm.vp.select.nxv2i1(<vscale x 2 x i1> %x, <vscale x 2 x i1> zeroinitializer, <vscale x 2 x i1> %y, i32 %evl)
+ ret <vscale x 2 x i1> %a
+}
+
+define <vscale x 2 x i1> @select_one_x(<vscale x 2 x i1> %x, <vscale x 2 x i1> %y, i32 zeroext %evl) {
+; CHECK-LABEL: select_one_x:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetvli a1, zero, e8, mf4, ta, ma
+; CHECK-NEXT:    vmset.m v8
+; CHECK-NEXT:    vsetvli zero, a0, e8, mf4, ta, ma
+; CHECK-NEXT:    vmor.mm v0, v0, v8
+; CHECK-NEXT:    ret
+  %a = call <vscale x 2 x i1> @llvm.vp.select.nxv2i1(<vscale x 2 x i1> %x, <vscale x 2 x i1> shufflevector (<vscale x 2 x i1> insertelement (<vscale x 2 x i1> undef, i1 true, i32 0), <vscale x 2 x i1> undef, <vscale x 2 x i32> zeroinitializer), <vscale x 2 x i1> %y, i32 %evl)
+ ret <vscale x 2 x i1> %a
+}



More information about the llvm-commits mailing list