Skip to content

[VP][RISCV] Introduce experimental.vp.popcount and RISC-V support. #74294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21761,6 +21761,39 @@ This intrinsic reverses the order of the first ``evl`` elements in a vector.
The lanes in the result vector disabled by ``mask`` are ``poison``. The
elements past ``evl`` are poison.


.. _int_experimental_vp_popcount:


'``llvm.experimental.vp.popcount``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Syntax:
"""""""
This is an overloaded intrinsic.

::

declare i32 @llvm.experimental.vp.popcount.v2i1(<2 x i1> %vec, <2 x i1> %mask, i32 %evl)
declare i32 @llvm.experimental.vp.popcount.nxv2i1(<vscale x 4 x i1> %vec, <vscale x 4 x i1> %mask, i32 %evl)

Overview:
"""""""""

Predicated population count of a vector mask.

Arguments:
""""""""""

The first and second argument are vector masks and have same number of elements.
The third argument is the explicit vector length of the operation.

Semantics:
""""""""""

This intrinsic population counts first ``evl`` elements activated by ``mask`` in a
vector.

.. _int_vp_load:

'``llvm.vp.load``' Intrinsic
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -2162,6 +2162,10 @@ let IntrProperties = [IntrNoMem, IntrNoSync, IntrWillReturn] in {
llvm_anyvector_ty,
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
llvm_i32_ty]>;
def int_experimental_vp_popcount: DefaultAttrsIntrinsic<[llvm_i32_ty],
[ llvm_anyvector_ty,
LLVMMatchType<0>,
llvm_i32_ty]>;
}

let IntrProperties = [IntrNoMem, IntrNoSync, IntrWillReturn, ImmArg<ArgIndex<1>>] in {
Expand Down
6 changes: 6 additions & 0 deletions llvm/include/llvm/IR/VPIntrinsics.def
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,12 @@ END_REGISTER_VP(experimental_vp_reverse, EXPERIMENTAL_VP_REVERSE)

///// } Shuffles

// llvm.experimental.vp.popcount(x,mask,vlen)
BEGIN_REGISTER_VP(experimental_vp_popcount, 1, 2,
EXPERIMENTAL_VP_POPCOUNT, 0)
VP_PROPERTY_NO_FUNCTIONAL
END_REGISTER_VP(experimental_vp_popcount, EXPERIMENTAL_VP_POPCOUNT)

#undef BEGIN_REGISTER_VP
#undef BEGIN_REGISTER_VP_INTRINSIC
#undef BEGIN_REGISTER_VP_SDNODE
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
case ISD::LLRINT:
Res = PromoteIntRes_XRINT(N);
break;

case ISD::EXPERIMENTAL_VP_POPCOUNT:
Res = PromoteIntRes_VP_POPCOUNT(N);
break;
}

// If the result is null then the sub-method took care of registering it.
Expand Down Expand Up @@ -5882,6 +5886,12 @@ SDValue DAGTypeLegalizer::PromoteIntOp_EXTRACT_VECTOR_ELT(SDNode *N) {
return DAG.getAnyExtOrTrunc(Ext, dl, N->getValueType(0));
}

SDValue DAGTypeLegalizer::PromoteIntRes_VP_POPCOUNT(SDNode *N) {
SDLoc dl(N);
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
return DAG.getNode(N->getOpcode(), dl, NVT, N->ops());
}

SDValue DAGTypeLegalizer::PromoteIntOp_INSERT_SUBVECTOR(SDNode *N) {
SDLoc dl(N);
// The result type is equal to the first input operand's type, so the
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue PromoteIntRes_FunnelShift(SDNode *N);
SDValue PromoteIntRes_VPFunnelShift(SDNode *N);
SDValue PromoteIntRes_IS_FPCLASS(SDNode *N);
SDValue PromoteIntRes_VP_POPCOUNT(SDNode *N);

// Integer Operand Promotion.
bool PromoteIntegerOperand(SDNode *N, unsigned OpNo);
Expand Down Expand Up @@ -916,6 +917,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue SplitVecOp_FP_ROUND(SDNode *N);
SDValue SplitVecOp_FPOpDifferentTypes(SDNode *N);
SDValue SplitVecOp_FP_TO_XINT_SAT(SDNode *N);
SDValue SplitVecOp_VP_POPCOUNT(SDNode *N, unsigned OpNo);

//===--------------------------------------------------------------------===//
// Vector Widening Support: LegalizeVectorTypes.cpp
Expand Down Expand Up @@ -1023,6 +1025,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue WidenVecOp_VECREDUCE_SEQ(SDNode *N);
SDValue WidenVecOp_VP_REDUCE(SDNode *N);
SDValue WidenVecOp_ExpOp(SDNode *N);
SDValue WidenVecOp_VP_POPCOUNT(SDNode *N);

/// Helper function to generate a set of operations to perform
/// a vector operation for a wider type.
Expand Down
38 changes: 38 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3085,6 +3085,9 @@ bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
case ISD::VP_REDUCE_FMIN:
Res = SplitVecOp_VP_REDUCE(N, OpNo);
break;
case ISD::EXPERIMENTAL_VP_POPCOUNT:
Res = SplitVecOp_VP_POPCOUNT(N, OpNo);
break;
}

// If the result is null, the sub-method took care of registering results etc.
Expand Down Expand Up @@ -4031,6 +4034,31 @@ SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
}

SDValue DAGTypeLegalizer::SplitVecOp_VP_POPCOUNT(SDNode *N, unsigned OpNo) {
assert(N->isVPOpcode() && "Expected VP opcode");
assert(OpNo == 0 && "Can only split first operand");

unsigned Opc = N->getOpcode();
EVT ResVT = N->getValueType(0);
SDValue Lo, Hi;
SDLoc dl(N);

SDValue VecOp = N->getOperand(OpNo);
EVT VecVT = VecOp.getValueType();
assert(VecVT.isVector() && "Can only split reduce vector operand");
GetSplitVector(VecOp, Lo, Hi);

SDValue MaskLo, MaskHi;
std::tie(MaskLo, MaskHi) = SplitMask(N->getOperand(1));

SDValue EVLLo, EVLHi;
std::tie(EVLLo, EVLHi) = DAG.SplitEVL(N->getOperand(2), VecVT, dl);

SDValue ResLo = DAG.getNode(Opc, dl, ResVT, {Lo, MaskLo, EVLLo});
SDValue ResHi = DAG.getNode(Opc, dl, ResVT, {Hi, MaskHi, EVLHi});
return DAG.getNode(ISD::ADD, dl, ResVT, ResLo, ResHi);
}

//===----------------------------------------------------------------------===//
// Result Vector Widening
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -6120,6 +6148,9 @@ bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
case ISD::VP_REDUCE_FMIN:
Res = WidenVecOp_VP_REDUCE(N);
break;
case ISD::EXPERIMENTAL_VP_POPCOUNT:
Res = WidenVecOp_VP_POPCOUNT(N);
break;
}

// If Res is null, the sub-method took care of registering the result.
Expand Down Expand Up @@ -6883,6 +6914,13 @@ SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
DAG.getVectorIdxConstant(0, DL));
}

SDValue DAGTypeLegalizer::WidenVecOp_VP_POPCOUNT(SDNode *N) {
EVT ResVT = N->getValueType(0);
SDValue Op = GetWidenedVector(N->getOperand(0));
SDValue Mask = GetWidenedVector(N->getOperand(1));
return DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, Op, Mask,
N->getOperand(2));
}
//===----------------------------------------------------------------------===//
// Vector Widening Utilities
//===----------------------------------------------------------------------===//
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::VECTOR_REVERSE, VT, Custom);

setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
setOperationAction(ISD::EXPERIMENTAL_VP_POPCOUNT, VT, Custom);

setOperationPromotedToType(
ISD::VECTOR_SPLICE, VT,
Expand Down Expand Up @@ -1140,6 +1141,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
VT, Custom);

setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
setOperationAction(ISD::EXPERIMENTAL_VP_POPCOUNT, VT, Custom);
continue;
}

Expand Down Expand Up @@ -6607,6 +6609,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
return lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(Op, DAG, Subtarget);
case ISD::EXPERIMENTAL_VP_REVERSE:
return lowerVPReverseExperimental(Op, DAG);
case ISD::EXPERIMENTAL_VP_POPCOUNT:
return lowerVPPopcountExperimental(Op, DAG);
}
}

Expand Down Expand Up @@ -19744,6 +19748,26 @@ bool RISCVTargetLowering::lowerInterleaveIntrinsicToStore(IntrinsicInst *II,
return true;
}

SDValue
RISCVTargetLowering::lowerVPPopcountExperimental(SDValue N,
SelectionDAG &DAG) const {
SDValue Op = N.getOperand(0);
SDValue Mask = N.getOperand(1);
MVT VT = Op.getSimpleValueType();
SDLoc DL(N);
MVT XLenVT = Subtarget.getXLenVT();

MVT ContainerVT = VT;
if (VT.isFixedLengthVector()) {
ContainerVT = getContainerForFixedLengthVector(VT);
Op = convertToScalableVector(ContainerVT, Op, DAG, Subtarget);
Mask = convertToScalableVector(ContainerVT, Mask, DAG, Subtarget);
}

return DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Op, Mask,
N->getOperand(2));
}

MachineInstr *
RISCVTargetLowering::EmitKCFICheck(MachineBasicBlock &MBB,
MachineBasicBlock::instr_iterator &MBBI,
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,7 @@ class RISCVTargetLowering : public TargetLowering {
SDValue lowerVPExtMaskOp(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVPSetCCMaskOp(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVPReverseExperimental(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVPPopcountExperimental(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVPFPIntConvOp(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVPStridedLoad(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVPStridedStore(SDValue Op, SelectionDAG &DAG) const;
Expand Down
Loading