Skip to content

Commit dfd9bf7

Browse files
committed
[VP][RISCV] Add vp.cttz.elts intrinsic and its RISC-V codegen
This intrinsic is basically the VP version of `experimental.cttz.elts`.
1 parent 721c31e commit dfd9bf7

File tree

13 files changed

+440
-2
lines changed

13 files changed

+440
-2
lines changed

llvm/docs/LangRef.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24001,6 +24001,54 @@ Examples:
2400124001
%also.r = select <4 x i1> %mask, <4 x i32> %t, <4 x i32> poison
2400224002

2400324003

24004+
.. _int_vp_cttz_elts:
24005+
24006+
'``llvm.vp.cttz.elts.*``' Intrinsics
24007+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24008+
24009+
Syntax:
24010+
"""""""
24011+
This is an overloaded intrinsic. You can use ```llvm.vp.cttz.elts``` on any
24012+
vector of integer elements, both fixed width and scalable.
24013+
24014+
::
24015+
24016+
declare i32 @llvm.vp.cttz.elts.i32.v16i32 (<16 x i32> <op>, i1 <is_zero_poison>, <16 x i1> <mask>, i32 <vector_length>)
24017+
declare i64 @llvm.vp.cttz.elts.i64.nxv4i32 (<vscale x 4 x i32> <op>, i1 <is_zero_poison>, <vscale x 4 x i1> <mask>, i32 <vector_length>)
24018+
declare i64 @llvm.vp.cttz.elts.i64.v256i1 (<256 x i1> <op>, i1 <is_zero_poison>, <256 x i1> <mask>, i32 <vector_length>)
24019+
24020+
Overview:
24021+
"""""""""
24022+
24023+
This '```llvm.vp.cttz.elts```' intrinsic counts the number of trailing zero
24024+
elements of a vector. This is basically the vector-predicated version of
24025+
'```llvm.experimental.cttz.elts```'.
24026+
24027+
Arguments:
24028+
""""""""""
24029+
24030+
The first argument is the vector to be counted. This argument must be a vector
24031+
with integer element type. The return type must also be an integer type which is
24032+
wide enough to hold the maximum number of elements of the source vector. The
24033+
behavior of this intrinsic is undefined if the return type is not wide enough
24034+
for the number of elements in the input vector.
24035+
24036+
The second argument is a constant flag that indicates whether the intrinsic
24037+
returns a valid result if the first argument is all zero.
24038+
24039+
The third operand is the vector mask and has the same number of elements as the
24040+
input vector type. The fourth operand is the explicit vector length of the
24041+
operation.
24042+
24043+
Semantics:
24044+
""""""""""
24045+
24046+
The '``llvm.vp.cttz.elts``' intrinsic counts the trailing (least
24047+
significant / lowest-numbered) zero elements in the first operand on each
24048+
enabled lane. If the first argument is all zero and the second argument is true,
24049+
the result is poison. Otherwise, it returns the explicit vector length (i.e. the
24050+
fourth operand).
24051+
2400424052
.. _int_vp_sadd_sat:
2400524053

2400624054
'``llvm.vp.sadd.sat.*``' Intrinsics

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5307,6 +5307,11 @@ class TargetLowering : public TargetLoweringBase {
53075307
/// \returns The expansion result or SDValue() if it fails.
53085308
SDValue expandVPCTTZ(SDNode *N, SelectionDAG &DAG) const;
53095309

5310+
/// Expand VP_CTTZ_ELTS/VP_CTTZ_ELTS_ZERO_UNDEF nodes.
5311+
/// \param N Node to expand
5312+
/// \returns The expansion result or SDValue() if it fails.
5313+
SDValue expandVPCTTZElements(SDNode *N, SelectionDAG &DAG) const;
5314+
53105315
/// Expand ABS nodes. Expands vector/scalar ABS nodes,
53115316
/// vector nodes can only succeed if all operations are legal/custom.
53125317
/// (ABS x) -> (XOR (ADD x, (SRA x, type_size)), (SRA x, type_size))

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,6 +2255,12 @@ let IntrProperties = [IntrNoMem, IntrNoSync, IntrWillReturn, ImmArg<ArgIndex<1>>
22552255
llvm_i1_ty,
22562256
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>,
22572257
llvm_i32_ty]>;
2258+
2259+
def int_vp_cttz_elts : DefaultAttrsIntrinsic<[ llvm_anyint_ty ],
2260+
[ llvm_anyvector_ty,
2261+
llvm_i1_ty,
2262+
LLVMScalarOrSameVectorWidth<1, llvm_i1_ty>,
2263+
llvm_i32_ty]>;
22582264
}
22592265

22602266
def int_get_active_lane_mask:

llvm/include/llvm/IR/VPIntrinsics.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,15 @@ BEGIN_REGISTER_VP_SDNODE(VP_CTTZ_ZERO_UNDEF, -1, vp_cttz_zero_undef, 1, 2)
282282
END_REGISTER_VP_SDNODE(VP_CTTZ_ZERO_UNDEF)
283283
END_REGISTER_VP_INTRINSIC(vp_cttz)
284284

285+
// llvm.vp.cttz.elts(x,is_zero_poison,mask,vl)
286+
BEGIN_REGISTER_VP_INTRINSIC(vp_cttz_elts, 2, 3)
287+
VP_PROPERTY_NO_FUNCTIONAL
288+
BEGIN_REGISTER_VP_SDNODE(VP_CTTZ_ELTS, 0, vp_cttz_elts, 1, 2)
289+
END_REGISTER_VP_SDNODE(VP_CTTZ_ELTS)
290+
BEGIN_REGISTER_VP_SDNODE(VP_CTTZ_ELTS_ZERO_UNDEF, 0, vp_cttz_elts_zero_undef, 1, 2)
291+
END_REGISTER_VP_SDNODE(VP_CTTZ_ELTS_ZERO_UNDEF)
292+
END_REGISTER_VP_INTRINSIC(vp_cttz_elts)
293+
285294
// llvm.vp.fshl(x,y,z,mask,vlen)
286295
BEGIN_REGISTER_VP(vp_fshl, 3, 4, VP_FSHL, -1)
287296
VP_PROPERTY_FUNCTIONAL_INTRINSIC(fshl)

llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
7676
case ISD::VP_CTTZ:
7777
case ISD::CTTZ_ZERO_UNDEF:
7878
case ISD::CTTZ: Res = PromoteIntRes_CTTZ(N); break;
79+
case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
80+
case ISD::VP_CTTZ_ELTS:
81+
Res = PromoteIntRes_VP_CttzElements(N);
82+
break;
7983
case ISD::EXTRACT_VECTOR_ELT:
8084
Res = PromoteIntRes_EXTRACT_VECTOR_ELT(N); break;
8185
case ISD::LOAD: Res = PromoteIntRes_LOAD(cast<LoadSDNode>(N)); break;
@@ -724,6 +728,12 @@ SDValue DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) {
724728
N->getOperand(2));
725729
}
726730

731+
SDValue DAGTypeLegalizer::PromoteIntRes_VP_CttzElements(SDNode *N) {
732+
SDLoc DL(N);
733+
EVT NewVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
734+
return DAG.getNode(N->getOpcode(), DL, NewVT, N->ops());
735+
}
736+
727737
SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) {
728738
SDLoc dl(N);
729739
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));

llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
309309
SDValue PromoteIntRes_CTLZ(SDNode *N);
310310
SDValue PromoteIntRes_CTPOP_PARITY(SDNode *N);
311311
SDValue PromoteIntRes_CTTZ(SDNode *N);
312+
SDValue PromoteIntRes_VP_CttzElements(SDNode *N);
312313
SDValue PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N);
313314
SDValue PromoteIntRes_FP_TO_XINT(SDNode *N);
314315
SDValue PromoteIntRes_FP_TO_XINT_SAT(SDNode *N);
@@ -912,6 +913,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
912913
SDValue SplitVecOp_FP_ROUND(SDNode *N);
913914
SDValue SplitVecOp_FPOpDifferentTypes(SDNode *N);
914915
SDValue SplitVecOp_FP_TO_XINT_SAT(SDNode *N);
916+
SDValue SplitVecOp_VP_CttzElements(SDNode *N);
915917

916918
//===--------------------------------------------------------------------===//
917919
// Vector Widening Support: LegalizeVectorTypes.cpp
@@ -1019,6 +1021,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
10191021
SDValue WidenVecOp_VECREDUCE_SEQ(SDNode *N);
10201022
SDValue WidenVecOp_VP_REDUCE(SDNode *N);
10211023
SDValue WidenVecOp_ExpOp(SDNode *N);
1024+
SDValue WidenVecOp_VP_CttzElements(SDNode *N);
10221025

10231026
/// Helper function to generate a set of operations to perform
10241027
/// a vector operation for a wider type.

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,13 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
963963
return;
964964
}
965965
break;
966+
case ISD::VP_CTTZ_ELTS:
967+
case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
968+
if (SDValue Expanded = TLI.expandVPCTTZElements(Node, DAG)) {
969+
Results.push_back(Expanded);
970+
return;
971+
}
972+
break;
966973
case ISD::FSHL:
967974
case ISD::VP_FSHL:
968975
case ISD::FSHR:

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "LegalizeTypes.h"
2323
#include "llvm/ADT/SmallBitVector.h"
2424
#include "llvm/Analysis/MemoryLocation.h"
25+
#include "llvm/Analysis/ValueTracking.h"
2526
#include "llvm/Analysis/VectorUtils.h"
2627
#include "llvm/IR/DataLayout.h"
2728
#include "llvm/Support/ErrorHandling.h"
@@ -3098,6 +3099,10 @@ bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
30983099
case ISD::VP_REDUCE_FMIN:
30993100
Res = SplitVecOp_VP_REDUCE(N, OpNo);
31003101
break;
3102+
case ISD::VP_CTTZ_ELTS:
3103+
case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
3104+
Res = SplitVecOp_VP_CttzElements(N);
3105+
break;
31013106
}
31023107

31033108
// If the result is null, the sub-method took care of registering results etc.
@@ -4056,6 +4061,29 @@ SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
40564061
return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
40574062
}
40584063

4064+
SDValue DAGTypeLegalizer::SplitVecOp_VP_CttzElements(SDNode *N) {
4065+
SDLoc DL(N);
4066+
EVT ResVT = N->getValueType(0);
4067+
4068+
SDValue Lo, Hi;
4069+
SDValue VecOp = N->getOperand(0);
4070+
GetSplitVector(VecOp, Lo, Hi);
4071+
4072+
auto [MaskLo, MaskHi] = SplitMask(N->getOperand(1));
4073+
auto [EVLLo, EVLHi] =
4074+
DAG.SplitEVL(N->getOperand(2), VecOp.getValueType(), DL);
4075+
SDValue VLo = DAG.getZExtOrTrunc(EVLLo, DL, ResVT);
4076+
4077+
// if VP_CTTZ_ELTS(Lo) != EVLLo => VP_CTTZ_ELTS(Lo).
4078+
// else => EVLLo + VP_CTTZ_ELTS / VP_CTTZ_ELTS_ZERO_UNDEF(Hi).
4079+
SDValue ResLo = DAG.getNode(ISD::VP_CTTZ_ELTS, DL, ResVT, Lo, MaskLo, EVLLo);
4080+
SDValue ResLoNotEVL =
4081+
DAG.getSetCC(DL, getSetCCResultType(ResVT), ResLo, VLo, ISD::SETNE);
4082+
SDValue ResHi = DAG.getNode(N->getOpcode(), DL, ResVT, Hi, MaskHi, EVLHi);
4083+
return DAG.getSelect(DL, ResVT, ResLoNotEVL, ResLo,
4084+
DAG.getNode(ISD::ADD, DL, ResVT, VLo, ResHi));
4085+
}
4086+
40594087
//===----------------------------------------------------------------------===//
40604088
// Result Vector Widening
40614089
//===----------------------------------------------------------------------===//
@@ -6161,6 +6189,10 @@ bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
61616189
case ISD::VP_REDUCE_FMIN:
61626190
Res = WidenVecOp_VP_REDUCE(N);
61636191
break;
6192+
case ISD::VP_CTTZ_ELTS:
6193+
case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
6194+
Res = WidenVecOp_VP_CttzElements(N);
6195+
break;
61646196
}
61656197

61666198
// If Res is null, the sub-method took care of registering the result.
@@ -6924,6 +6956,35 @@ SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
69246956
DAG.getVectorIdxConstant(0, DL));
69256957
}
69266958

6959+
SDValue DAGTypeLegalizer::WidenVecOp_VP_CttzElements(SDNode *N) {
6960+
// Widen the result bit width if needed.
6961+
SDLoc DL(N);
6962+
EVT OrigResVT = N->getValueType(0);
6963+
const Function &F = DAG.getMachineFunction().getFunction();
6964+
6965+
SDValue Source = GetWidenedVector(N->getOperand(0));
6966+
EVT SrcVT = Source.getValueType();
6967+
SDValue Mask =
6968+
GetWidenedMask(N->getOperand(1), SrcVT.getVectorElementCount());
6969+
6970+
// Compute the number of bits that can fit the result.
6971+
ConstantRange CR(APInt(64, SrcVT.getVectorMinNumElements()));
6972+
if (SrcVT.isScalableVT())
6973+
CR = CR.umul_sat(getVScaleRange(&F, 64));
6974+
// If the zero-is-poison flag is set in the original intrinsic, we can
6975+
// assume the upper limit of the result is EVL - 1.
6976+
if (N->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6977+
CR = CR.subtract(APInt(64, 1));
6978+
6979+
unsigned NewResWidth = OrigResVT.getScalarSizeInBits();
6980+
NewResWidth = std::min(NewResWidth, unsigned(CR.getActiveBits()));
6981+
NewResWidth = std::max(llvm::bit_ceil(NewResWidth), 8U);
6982+
6983+
EVT NewResVT = EVT::getIntegerVT(*DAG.getContext(), NewResWidth);
6984+
return DAG.getNode(N->getOpcode(), DL, NewResVT, Source, Mask,
6985+
N->getOperand(2));
6986+
}
6987+
69276988
//===----------------------------------------------------------------------===//
69286989
// Vector Widening Utilities
69296990
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8076,6 +8076,11 @@ static unsigned getISDForVPIntrinsic(const VPIntrinsic &VPIntrin) {
80768076
ResOPC = IsZeroUndef ? ISD::VP_CTTZ_ZERO_UNDEF : ISD::VP_CTTZ;
80778077
break;
80788078
}
8079+
case Intrinsic::vp_cttz_elts: {
8080+
bool IsZeroPoison = cast<ConstantInt>(VPIntrin.getArgOperand(1))->isOne();
8081+
ResOPC = IsZeroPoison ? ISD::VP_CTTZ_ELTS_ZERO_UNDEF : ISD::VP_CTTZ_ELTS;
8082+
break;
8083+
}
80798084
#define HELPER_MAP_VPID_TO_VPSD(VPID, VPSD) \
80808085
case Intrinsic::VPID: \
80818086
ResOPC = ISD::VPSD; \
@@ -8428,7 +8433,9 @@ void SelectionDAGBuilder::visitVectorPredicationIntrinsic(
84288433
case ISD::VP_CTLZ:
84298434
case ISD::VP_CTLZ_ZERO_UNDEF:
84308435
case ISD::VP_CTTZ:
8431-
case ISD::VP_CTTZ_ZERO_UNDEF: {
8436+
case ISD::VP_CTTZ_ZERO_UNDEF:
8437+
case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
8438+
case ISD::VP_CTTZ_ELTS: {
84328439
SDValue Result =
84338440
DAG.getNode(Opcode, DL, VTs, {OpValues[0], OpValues[2], OpValues[3]});
84348441
setValue(&VPIntrin, Result);

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9074,6 +9074,38 @@ SDValue TargetLowering::expandVPCTTZ(SDNode *Node, SelectionDAG &DAG) const {
90749074
return DAG.getNode(ISD::VP_CTPOP, dl, VT, Tmp, Mask, VL);
90759075
}
90769076

9077+
SDValue TargetLowering::expandVPCTTZElements(SDNode *N,
9078+
SelectionDAG &DAG) const {
9079+
// %cond = to_bool_vec %source
9080+
// %splat = splat /*val=*/VL
9081+
// %tz = step_vector
9082+
// %v = vp.select %cond, /*true=*/tz, /*false=*/%splat
9083+
// %r = vp.reduce.umin %v
9084+
SDLoc DL(N);
9085+
SDValue Source = N->getOperand(0);
9086+
SDValue Mask = N->getOperand(1);
9087+
SDValue EVL = N->getOperand(2);
9088+
EVT SrcVT = Source.getValueType();
9089+
EVT ResVT = N->getValueType(0);
9090+
EVT ResVecVT =
9091+
EVT::getVectorVT(*DAG.getContext(), ResVT, SrcVT.getVectorElementCount());
9092+
9093+
// Convert to boolean vector.
9094+
if (SrcVT.getScalarType() != MVT::i1) {
9095+
SDValue AllZero = DAG.getConstant(0, DL, SrcVT);
9096+
SrcVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
9097+
SrcVT.getVectorElementCount());
9098+
Source = DAG.getSetCC(DL, SrcVT, Source, AllZero, ISD::SETNE);
9099+
}
9100+
9101+
SDValue ExtEVL = DAG.getZExtOrTrunc(EVL, DL, ResVT);
9102+
SDValue Splat = DAG.getSplat(ResVecVT, DL, ExtEVL);
9103+
SDValue StepVec = DAG.getStepVector(DL, ResVecVT);
9104+
SDValue Select =
9105+
DAG.getNode(ISD::VP_SELECT, DL, ResVecVT, Source, StepVec, Splat, EVL);
9106+
return DAG.getNode(ISD::VP_REDUCE_UMIN, DL, ResVT, ExtEVL, Select, Mask, EVL);
9107+
}
9108+
90779109
SDValue TargetLowering::expandABS(SDNode *N, SelectionDAG &DAG,
90789110
bool IsNegative) const {
90799111
SDLoc dl(N);

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
698698
ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
699699
ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
700700
ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
701-
ISD::VP_USUBSAT};
701+
ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF};
702702

703703
static const unsigned FloatingPointVPOps[] = {
704704
ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
@@ -759,6 +759,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
759759
{ISD::SELECT_CC, ISD::VSELECT, ISD::VP_MERGE, ISD::VP_SELECT}, VT,
760760
Expand);
761761

762+
setOperationAction({ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF}, VT,
763+
Custom);
764+
762765
setOperationAction({ISD::VP_AND, ISD::VP_OR, ISD::VP_XOR}, VT, Custom);
763766

764767
setOperationAction(
@@ -5341,6 +5344,45 @@ RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(SDValue Op,
53415344
return Res;
53425345
}
53435346

5347+
SDValue RISCVTargetLowering::lowerVPCttzElements(SDValue Op,
5348+
SelectionDAG &DAG) const {
5349+
SDLoc DL(Op);
5350+
MVT XLenVT = Subtarget.getXLenVT();
5351+
SDValue Source = Op->getOperand(0);
5352+
MVT SrcVT = Source.getSimpleValueType();
5353+
SDValue Mask = Op->getOperand(1);
5354+
SDValue EVL = Op->getOperand(2);
5355+
5356+
if (SrcVT.isFixedLengthVector()) {
5357+
MVT ContainerVT = getContainerForFixedLengthVector(SrcVT);
5358+
Source = convertToScalableVector(ContainerVT, Source, DAG, Subtarget);
5359+
Mask = convertToScalableVector(getMaskTypeFor(ContainerVT), Mask, DAG,
5360+
Subtarget);
5361+
SrcVT = ContainerVT;
5362+
}
5363+
5364+
// Convert to boolean vector.
5365+
if (SrcVT.getScalarType() != MVT::i1) {
5366+
SDValue AllZero = DAG.getConstant(0, DL, SrcVT);
5367+
SrcVT = MVT::getVectorVT(MVT::i1, SrcVT.getVectorElementCount());
5368+
Source = DAG.getNode(RISCVISD::SETCC_VL, DL, SrcVT,
5369+
{Source, AllZero, DAG.getCondCode(ISD::SETNE),
5370+
DAG.getUNDEF(SrcVT), Mask, EVL});
5371+
}
5372+
5373+
SDValue Res = DAG.getNode(RISCVISD::VFIRST_VL, DL, XLenVT, Source, Mask, EVL);
5374+
if (Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
5375+
// In this case, we can interpret poison as -1, so nothing to do further.
5376+
return Res;
5377+
5378+
// Convert -1 to VL.
5379+
SDValue SetCC =
5380+
DAG.getSetCC(DL, XLenVT, Res, DAG.getConstant(0, DL, XLenVT), ISD::SETLT);
5381+
Res = DAG.getSelect(DL, XLenVT, SetCC, DAG.getZExtOrTrunc(EVL, DL, XLenVT),
5382+
Res);
5383+
return DAG.getNode(ISD::TRUNCATE, DL, Op.getValueType(), Res);
5384+
}
5385+
53445386
// While RVV has alignment restrictions, we should always be able to load as a
53455387
// legal equivalently-sized byte-typed vector instead. This method is
53465388
// responsible for re-expressing a ISD::LOAD via a correctly-aligned type. If
@@ -6595,6 +6637,9 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
65956637
if (Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
65966638
return lowerVectorMaskVecReduction(Op, DAG, /*IsVP*/ true);
65976639
return lowerVPREDUCE(Op, DAG);
6640+
case ISD::VP_CTTZ_ELTS:
6641+
case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
6642+
return lowerVPCttzElements(Op, DAG);
65986643
case ISD::UNDEF: {
65996644
MVT ContainerVT = getContainerForFixedLengthVector(Op.getSimpleValueType());
66006645
return convertFromScalableVector(Op.getSimpleValueType(),

llvm/lib/Target/RISCV/RISCVISelLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ class RISCVTargetLowering : public TargetLowering {
961961
SDValue lowerVPFPIntConvOp(SDValue Op, SelectionDAG &DAG) const;
962962
SDValue lowerVPStridedLoad(SDValue Op, SelectionDAG &DAG) const;
963963
SDValue lowerVPStridedStore(SDValue Op, SelectionDAG &DAG) const;
964+
SDValue lowerVPCttzElements(SDValue Op, SelectionDAG &DAG) const;
964965
SDValue lowerFixedLengthVectorExtendToRVV(SDValue Op, SelectionDAG &DAG,
965966
unsigned ExtendOpc) const;
966967
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;

0 commit comments

Comments
 (0)