[llvm] 07ca13f - [RISCV] Add support for fixed vector mask logic operations.
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 16 09:37:30 PST 2021
Author: Craig Topper
Date: 2021-02-16T09:34:00-08:00
New Revision: 07ca13fe0766ded6fd69a6729275020e6b4c0b1b
URL: https://github.com/llvm/llvm-project/commit/07ca13fe0766ded6fd69a6729275020e6b4c0b1b
DIFF: https://github.com/llvm/llvm-project/commit/07ca13fe0766ded6fd69a6729275020e6b4c0b1b.diff
LOG: [RISCV] Add support for fixed vector mask logic operations.
Reviewed By: frasercrmck
Differential Revision: https://reviews.llvm.org/D96741
Added:
llvm/test/CodeGen/RISCV/rvv/fixed-vectors-mask-logic.ll
Modified:
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.h
llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index f7b7fc8510b0..c2ac6a588fc9 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -531,6 +531,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
// Operations below are
diff erent for between masks and other vectors.
if (VT.getVectorElementType() == MVT::i1) {
+ setOperationAction(ISD::AND, VT, Custom);
+ setOperationAction(ISD::OR, VT, Custom);
+ setOperationAction(ISD::XOR, VT, Custom);
setOperationAction(ISD::SETCC, VT, Custom);
continue;
}
@@ -1209,11 +1212,14 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
case ISD::MUL:
return lowerToScalableOp(Op, DAG, RISCVISD::MUL_VL);
case ISD::AND:
- return lowerToScalableOp(Op, DAG, RISCVISD::AND_VL);
+ return lowerFixedLengthVectorLogicOpToRVV(Op, DAG, RISCVISD::VMAND_VL,
+ RISCVISD::AND_VL);
case ISD::OR:
- return lowerToScalableOp(Op, DAG, RISCVISD::OR_VL);
+ return lowerFixedLengthVectorLogicOpToRVV(Op, DAG, RISCVISD::VMOR_VL,
+ RISCVISD::OR_VL);
case ISD::XOR:
- return lowerToScalableOp(Op, DAG, RISCVISD::XOR_VL);
+ return lowerFixedLengthVectorLogicOpToRVV(Op, DAG, RISCVISD::VMXOR_VL,
+ RISCVISD::XOR_VL);
case ISD::SDIV:
return lowerToScalableOp(Op, DAG, RISCVISD::SDIV_VL);
case ISD::SREM:
@@ -2231,8 +2237,19 @@ RISCVTargetLowering::lowerFixedLengthVectorSetccToRVV(SDValue Op,
return convertFromScalableVector(VT, Cmp, DAG, Subtarget);
}
+SDValue RISCVTargetLowering::lowerFixedLengthVectorLogicOpToRVV(
+ SDValue Op, SelectionDAG &DAG, unsigned MaskOpc, unsigned VecOpc) const {
+ MVT VT = Op.getSimpleValueType();
+
+ if (VT.getVectorElementType() == MVT::i1)
+ return lowerToScalableOp(Op, DAG, MaskOpc, /*HasMask*/ false);
+
+ return lowerToScalableOp(Op, DAG, VecOpc, /*HasMask*/ true);
+}
+
SDValue RISCVTargetLowering::lowerToScalableOp(SDValue Op, SelectionDAG &DAG,
- unsigned NewOpc) const {
+ unsigned NewOpc,
+ bool HasMask) const {
MVT VT = Op.getSimpleValueType();
assert(useRVVForFixedLengthVectorVT(VT) &&
"Only expected to lower fixed length vector operation!");
@@ -2258,7 +2275,8 @@ SDValue RISCVTargetLowering::lowerToScalableOp(SDValue Op, SelectionDAG &DAG,
SDLoc DL(Op);
SDValue Mask, VL;
std::tie(Mask, VL) = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget);
- Ops.push_back(Mask);
+ if (HasMask)
+ Ops.push_back(Mask);
Ops.push_back(VL);
SDValue ScalableRes = DAG.getNode(NewOpc, DL, ContainerVT, Ops);
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 74fe07a8b7f3..9b0503a48817 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -407,8 +407,11 @@ class RISCVTargetLowering : public TargetLowering {
SDValue lowerFixedLengthVectorLoadToRVV(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFixedLengthVectorStoreToRVV(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFixedLengthVectorSetccToRVV(SDValue Op, SelectionDAG &DAG) const;
- SDValue lowerToScalableOp(SDValue Op, SelectionDAG &DAG,
- unsigned NewOpc) const;
+ SDValue lowerFixedLengthVectorLogicOpToRVV(SDValue Op, SelectionDAG &DAG,
+ unsigned MaskOpc,
+ unsigned VecOpc) const;
+ SDValue lowerToScalableOp(SDValue Op, SelectionDAG &DAG, unsigned NewOpc,
+ bool HasMask = true) const;
bool isEligibleForTailCallOptimization(
CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td
index da515486b902..7eb569d17ca2 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td
@@ -126,6 +126,9 @@ def riscv_vmset_vl : SDNode<"RISCVISD::VMSET_VL", SDT_RISCVVMSETCLR_VL>;
def true_mask : PatLeaf<(riscv_vmset_vl (XLenVT srcvalue))>;
+def riscv_vmnot_vl : PatFrag<(ops node:$rs, node:$vl),
+ (riscv_vmxor_vl node:$rs, true_mask, node:$vl)>;
+
// Ignore the vl operand.
def SplatFPOp : PatFrag<(ops node:$op),
(riscv_vfmv_v_f_vl node:$op, srcvalue)>;
@@ -558,15 +561,41 @@ foreach mti = AllMasks in {
(!cast<Instruction>("PseudoVMXOR_MM_" # mti.LMul.MX)
VR:$rs1, VR:$rs2, GPR:$vl, mti.SEW)>;
- // FIXME: Add remaining mask instructions.
- def : Pat<(mti.Mask (riscv_vmxor_vl (riscv_vmor_vl VR:$rs1, VR:$rs2,
+ def : Pat<(mti.Mask (riscv_vmand_vl (riscv_vmnot_vl VR:$rs1,
+ (XLenVT (VLOp GPR:$vl))),
+ VR:$rs2, (XLenVT (VLOp GPR:$vl)))),
+ (!cast<Instruction>("PseudoVMANDNOT_MM_" # mti.LMul.MX)
+ VR:$rs1, VR:$rs2, GPR:$vl, mti.SEW)>;
+ def : Pat<(mti.Mask (riscv_vmor_vl (riscv_vmnot_vl VR:$rs1,
+ (XLenVT (VLOp GPR:$vl))),
+ VR:$rs2, (XLenVT (VLOp GPR:$vl)))),
+ (!cast<Instruction>("PseudoVMORNOT_MM_" # mti.LMul.MX)
+ VR:$rs1, VR:$rs2, GPR:$vl, mti.SEW)>;
+ // XOR is associative so we need 2 patterns for VMXNOR.
+ def : Pat<(mti.Mask (riscv_vmxor_vl (riscv_vmnot_vl VR:$rs1,
+ (XLenVT (VLOp GPR:$vl))),
+ VR:$rs2, (XLenVT (VLOp GPR:$vl)))),
+ (!cast<Instruction>("PseudoVMXNOR_MM_" # mti.LMul.MX)
+ VR:$rs1, VR:$rs2, GPR:$vl, mti.SEW)>;
+
+ def : Pat<(mti.Mask (riscv_vmnot_vl (riscv_vmand_vl VR:$rs1, VR:$rs2,
+ (XLenVT (VLOp GPR:$vl))),
+ (XLenVT (VLOp GPR:$vl)))),
+ (!cast<Instruction>("PseudoVMNAND_MM_" # mti.LMul.MX)
+ VR:$rs1, VR:$rs2, GPR:$vl, mti.SEW)>;
+ def : Pat<(mti.Mask (riscv_vmnot_vl (riscv_vmor_vl VR:$rs1, VR:$rs2,
(XLenVT (VLOp GPR:$vl))),
- true_mask, (XLenVT (VLOp GPR:$vl)))),
+ (XLenVT (VLOp GPR:$vl)))),
(!cast<Instruction>("PseudoVMNOR_MM_" # mti.LMul.MX)
VR:$rs1, VR:$rs2, GPR:$vl, mti.SEW)>;
+ def : Pat<(mti.Mask (riscv_vmnot_vl (riscv_vmxor_vl VR:$rs1, VR:$rs2,
+ (XLenVT (VLOp GPR:$vl))),
+ (XLenVT (VLOp GPR:$vl)))),
+ (!cast<Instruction>("PseudoVMXNOR_MM_" # mti.LMul.MX)
+ VR:$rs1, VR:$rs2, GPR:$vl, mti.SEW)>;
// Match the not idiom to the vnot.mm pseudo.
- def : Pat<(mti.Mask (riscv_vmxor_vl VR:$rs, true_mask, (XLenVT (VLOp GPR:$vl)))),
+ def : Pat<(mti.Mask (riscv_vmnot_vl VR:$rs, (XLenVT (VLOp GPR:$vl)))),
(!cast<Instruction>("PseudoVMNAND_MM_" # mti.LMul.MX)
VR:$rs, VR:$rs, GPR:$vl, mti.SEW)>;
}
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-mask-logic.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-mask-logic.ll
new file mode 100644
index 000000000000..89eeebf0aa2e
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-mask-logic.ll
@@ -0,0 +1,180 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-v -verify-machineinstrs -riscv-v-vector-bits-min=128 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-v -verify-machineinstrs -riscv-v-vector-bits-min=128 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-v -verify-machineinstrs -riscv-v-vector-bits-min=128 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-v -verify-machineinstrs -riscv-v-vector-bits-min=128 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK
+
+define void @and_v8i1(<8 x i1>* %x, <8 x i1>* %y) {
+; CHECK-LABEL: and_v8i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 8
+; CHECK-NEXT: vsetvli a2, a2, e8,m1,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmand.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <8 x i1>, <8 x i1>* %x
+ %b = load <8 x i1>, <8 x i1>* %y
+ %c = and <8 x i1> %a, %b
+ store <8 x i1> %c, <8 x i1>* %x
+ ret void
+}
+
+define void @or_v16i1(<16 x i1>* %x, <16 x i1>* %y) {
+; CHECK-LABEL: or_v16i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 16
+; CHECK-NEXT: vsetvli a2, a2, e8,m1,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmor.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <16 x i1>, <16 x i1>* %x
+ %b = load <16 x i1>, <16 x i1>* %y
+ %c = or <16 x i1> %a, %b
+ store <16 x i1> %c, <16 x i1>* %x
+ ret void
+}
+
+define void @xor_v32i1(<32 x i1>* %x, <32 x i1>* %y) {
+; CHECK-LABEL: xor_v32i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 32
+; CHECK-NEXT: vsetvli a2, a2, e8,m2,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmxor.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <32 x i1>, <32 x i1>* %x
+ %b = load <32 x i1>, <32 x i1>* %y
+ %c = xor <32 x i1> %a, %b
+ store <32 x i1> %c, <32 x i1>* %x
+ ret void
+}
+
+define void @not_v64i1(<64 x i1>* %x, <64 x i1>* %y) {
+; CHECK-LABEL: not_v64i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a1, zero, 64
+; CHECK-NEXT: vsetvli a1, a1, e8,m4,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vmnand.mm v25, v25, v25
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <64 x i1>, <64 x i1>* %x
+ %b = load <64 x i1>, <64 x i1>* %y
+ %c = xor <64 x i1> %a, <i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1>
+ store <64 x i1> %c, <64 x i1>* %x
+ ret void
+}
+
+define void @andnot_v8i1(<8 x i1>* %x, <8 x i1>* %y) {
+; CHECK-LABEL: andnot_v8i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 8
+; CHECK-NEXT: vsetvli a2, a2, e8,m1,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmandnot.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <8 x i1>, <8 x i1>* %x
+ %b = load <8 x i1>, <8 x i1>* %y
+ %c = xor <8 x i1> %a, <i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1>
+ %d = and <8 x i1> %b, %c
+ store <8 x i1> %d, <8 x i1>* %x
+ ret void
+}
+
+define void @ornot_v16i1(<16 x i1>* %x, <16 x i1>* %y) {
+; CHECK-LABEL: ornot_v16i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 16
+; CHECK-NEXT: vsetvli a2, a2, e8,m1,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmornot.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <16 x i1>, <16 x i1>* %x
+ %b = load <16 x i1>, <16 x i1>* %y
+ %c = xor <16 x i1> %a, <i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1>
+ %d = or <16 x i1> %b, %c
+ store <16 x i1> %d, <16 x i1>* %x
+ ret void
+}
+
+define void @xornot_v32i1(<32 x i1>* %x, <32 x i1>* %y) {
+; CHECK-LABEL: xornot_v32i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 32
+; CHECK-NEXT: vsetvli a2, a2, e8,m2,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmxnor.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <32 x i1>, <32 x i1>* %x
+ %b = load <32 x i1>, <32 x i1>* %y
+ %c = xor <32 x i1> %a, <i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1>
+ %d = xor <32 x i1> %b, %c
+ store <32 x i1> %d, <32 x i1>* %x
+ ret void
+}
+
+define void @nand_v8i1(<8 x i1>* %x, <8 x i1>* %y) {
+; CHECK-LABEL: nand_v8i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 8
+; CHECK-NEXT: vsetvli a2, a2, e8,m1,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmnand.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <8 x i1>, <8 x i1>* %x
+ %b = load <8 x i1>, <8 x i1>* %y
+ %c = and <8 x i1> %a, %b
+ %d = xor <8 x i1> %c, <i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1>
+ store <8 x i1> %d, <8 x i1>* %x
+ ret void
+}
+
+define void @nor_v16i1(<16 x i1>* %x, <16 x i1>* %y) {
+; CHECK-LABEL: nor_v16i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 16
+; CHECK-NEXT: vsetvli a2, a2, e8,m1,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmnor.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <16 x i1>, <16 x i1>* %x
+ %b = load <16 x i1>, <16 x i1>* %y
+ %c = or <16 x i1> %a, %b
+ %d = xor <16 x i1> %c, <i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1>
+ store <16 x i1> %d, <16 x i1>* %x
+ ret void
+}
+
+define void @xnor_v32i1(<32 x i1>* %x, <32 x i1>* %y) {
+; CHECK-LABEL: xnor_v32i1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a2, zero, 32
+; CHECK-NEXT: vsetvli a2, a2, e8,m2,ta,mu
+; CHECK-NEXT: vle1.v v25, (a0)
+; CHECK-NEXT: vle1.v v26, (a1)
+; CHECK-NEXT: vmxnor.mm v25, v25, v26
+; CHECK-NEXT: vse1.v v25, (a0)
+; CHECK-NEXT: ret
+ %a = load <32 x i1>, <32 x i1>* %x
+ %b = load <32 x i1>, <32 x i1>* %y
+ %c = xor <32 x i1> %a, %b
+ %d = xor <32 x i1> %c, <i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1>
+ store <32 x i1> %d, <32 x i1>* %x
+ ret void
+}
More information about the llvm-commits
mailing list