Skip to content

Commit 748ae52

Browse files
committed
[IR][SVE] Add new llvm.experimental.stepvector intrinsic
This patch adds a new llvm.experimental.stepvector intrinsic, which takes no arguments and returns a linear integer sequence of values of the form <0, 1, ...>. It is primarily intended for scalable vectors, although it will work for fixed width vectors too. It is intended that later patches will make use of this new intrinsic when vectorising induction variables, currently only supported for fixed width. I've added a new CreateStepVector method to the IRBuilder, which will generate a call to this intrinsic for scalable vectors and fall back on creating a ConstantVector for fixed width. For scalable vectors this intrinsic is lowered to a new ISD node called STEP_VECTOR, which takes a single constant integer argument as the step. During lowering this argument is set to a value of 1. The reason for this additional argument at the codegen level is because in future patches we will introduce various generic DAG combines such as mul step_vector(1), 2 -> step_vector(2) add step_vector(1), step_vector(1) -> step_vector(2) shl step_vector(1), 1 -> step_vector(2) etc. that encourage a canonical format for all targets. This hopefully means all other targets supporting scalable vectors can benefit from this too. I've added cost model tests for both fixed width and scalable vectors: llvm/test/Analysis/CostModel/AArch64/neon-stepvector.ll llvm/test/Analysis/CostModel/AArch64/sve-stepvector.ll as well as codegen lowering tests for fixed width and scalable vectors: llvm/test/CodeGen/AArch64/neon-stepvector.ll llvm/test/CodeGen/AArch64/sve-stepvector.ll See this thread for discussion of the intrinsic: https://lists.llvm.org/pipermail/llvm-dev/2021-January/147943.html
1 parent 9447077 commit 748ae52

26 files changed

+652
-1
lines changed

llvm/docs/LangRef.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16673,6 +16673,36 @@ The first two operands are vectors with the same type. The third argument
1667316673
the source/result vector. The ``imm`` is a signed integer constant in the range
1667416674
``-VL <= imm < VL``. For values outside of this range the result is poison.
1667516675

16676+
16677+
'``llvm.experimental.stepvector``' Intrinsic
16678+
16679+
This is an overloaded intrinsic. You can use ``llvm.experimental.stepvector``
16680+
to generate a vector whose lane values comprise the linear sequence
16681+
<0, 1, 2, ...>. It is primarily intended for scalable vectors.
16682+
16683+
::
16684+
16685+
declare <vscale x 4 x i32> @llvm.experimental.stepvector.nxv4i32()
16686+
declare <vscale x 8 x i16> @llvm.experimental.stepvector.nxv8i16()
16687+
16688+
The '``llvm.experimental.stepvector``' intrinsics are used to create vectors
16689+
of integers whose elements contain a linear sequence of values starting from 0
16690+
with a step of 1. This experimental intrinsic can only be used for vectors
16691+
with integer elements that are at least 8 bits in size. If the sequence value
16692+
exceeds the allowed limit for the element type then the result for that lane is
16693+
undefined.
16694+
16695+
These intrinsics work for both fixed and scalable vectors. While this intrinsic
16696+
is marked as experimental, the recommended way to express this operation for
16697+
fixed-width vectors is still to generate a constant vector instead.
16698+
16699+
16700+
Arguments:
16701+
""""""""""
16702+
16703+
None.
16704+
16705+
1667616706
Matrix Intrinsics
1667716707
-----------------
1667816708

llvm/include/llvm/CodeGen/BasicTTIImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,12 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
12491249
return thisT()->getGatherScatterOpCost(Instruction::Load, RetTy, Args[0],
12501250
VarMask, Alignment, CostKind, I);
12511251
}
1252+
case Intrinsic::experimental_stepvector: {
1253+
if (isa<ScalableVectorType>(RetTy))
1254+
return BaseT::getIntrinsicInstrCost(ICA, CostKind);
1255+
// The cost of materialising a constant integer vector.
1256+
return TargetTransformInfo::TCC_Basic;
1257+
}
12521258
case Intrinsic::experimental_vector_extract: {
12531259
// FIXME: Handle case where a scalable vector is extracted from a scalable
12541260
// vector

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,14 @@ enum NodeType {
592592
/// scalars should have the same type.
593593
SPLAT_VECTOR_PARTS,
594594

595+
/// STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised
596+
/// of a linear sequence of unsigned values starting from 0 with a step of
597+
/// IMM, where IMM must be a constant positive integer value. The operation
598+
/// does not support returning fixed-width vectors or non-constant operands.
599+
/// If the sequence value exceeds the limit allowed for the element type then
600+
/// the values for those lanes are undefined.
601+
STEP_VECTOR,
602+
595603
/// MULHU/MULHS - Multiply high - Multiply two integers of type iN,
596604
/// producing an unsigned/signed value of type i[2*N], then return the top
597605
/// part.

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,10 @@ class SelectionDAG {
833833
return getNode(ISD::SPLAT_VECTOR, DL, VT, Op);
834834
}
835835

836+
/// Returns a vector of type ResVT whose elements contain the linear sequence
837+
/// <0, Step, Step * 2, Step * 3, ...>
838+
SDValue getStepVector(const SDLoc &DL, EVT ResVT, SDValue Step);
839+
836840
/// Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to
837841
/// the shuffle node in input but with swapped operands.
838842
///

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,9 @@ class IRBuilderBase {
854854
/// will be the same type as that of \p Scaling.
855855
Value *CreateVScale(Constant *Scaling, const Twine &Name = "");
856856

857+
/// Creates a vector of type \p DstType with the linear sequence <0, 1, ...>
858+
Value *CreateStepVector(Type *DstType, const Twine &Name = "");
859+
857860
/// Create a call to intrinsic \p ID with 1 operand which is mangled on its
858861
/// type.
859862
CallInst *CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V,

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,9 @@ def int_is_constant : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty],
13371337
def int_ptrmask: DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>, llvm_anyint_ty],
13381338
[IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
13391339

1340+
def int_experimental_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
1341+
[], [IntrNoMem]>;
1342+
13401343
//===---------------- Vector Predication Intrinsics --------------===//
13411344

13421345
// Speculatable Binary operators

llvm/include/llvm/Target/TargetSelectionDAG.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,8 @@ def vector_reverse : SDNode<"ISD::VECTOR_REVERSE", SDTVecReverse>;
664664
def vector_splice : SDNode<"ISD::VECTOR_SPLICE", SDTVecSlice, []>;
665665
def build_vector : SDNode<"ISD::BUILD_VECTOR", SDTypeProfile<1, -1, []>, []>;
666666
def splat_vector : SDNode<"ISD::SPLAT_VECTOR", SDTypeProfile<1, 1, []>, []>;
667+
def step_vector : SDNode<"ISD::STEP_VECTOR", SDTypeProfile<1, 1,
668+
[SDTCisVec<0>, SDTCisInt<1>]>, []>;
667669
def scalar_to_vector : SDNode<"ISD::SCALAR_TO_VECTOR", SDTypeProfile<1, 1, []>,
668670
[]>;
669671

llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
110110
Res = PromoteIntRes_SCALAR_TO_VECTOR(N); break;
111111
case ISD::SPLAT_VECTOR:
112112
Res = PromoteIntRes_SPLAT_VECTOR(N); break;
113+
case ISD::STEP_VECTOR: Res = PromoteIntRes_STEP_VECTOR(N); break;
113114
case ISD::CONCAT_VECTORS:
114115
Res = PromoteIntRes_CONCAT_VECTORS(N); break;
115116

@@ -4782,6 +4783,18 @@ SDValue DAGTypeLegalizer::PromoteIntRes_SPLAT_VECTOR(SDNode *N) {
47824783
return DAG.getNode(ISD::SPLAT_VECTOR, dl, NOutVT, Op);
47834784
}
47844785

4786+
SDValue DAGTypeLegalizer::PromoteIntRes_STEP_VECTOR(SDNode *N) {
4787+
SDLoc dl(N);
4788+
EVT OutVT = N->getValueType(0);
4789+
EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT);
4790+
assert(NOutVT.isVector() && "Type must be promoted to a vector type");
4791+
EVT NOutElemVT = TLI.getTypeToTransformTo(*DAG.getContext(),
4792+
NOutVT.getVectorElementType());
4793+
APInt StepVal = cast<ConstantSDNode>(N->getOperand(0))->getAPIntValue();
4794+
SDValue Step = DAG.getConstant(StepVal.getZExtValue(), dl, NOutElemVT);
4795+
return DAG.getStepVector(dl, NOutVT, Step);
4796+
}
4797+
47854798
SDValue DAGTypeLegalizer::PromoteIntRes_CONCAT_VECTORS(SDNode *N) {
47864799
SDLoc dl(N);
47874800

llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
304304
SDValue PromoteIntRes_BUILD_VECTOR(SDNode *N);
305305
SDValue PromoteIntRes_SCALAR_TO_VECTOR(SDNode *N);
306306
SDValue PromoteIntRes_SPLAT_VECTOR(SDNode *N);
307+
SDValue PromoteIntRes_STEP_VECTOR(SDNode *N);
307308
SDValue PromoteIntRes_EXTEND_VECTOR_INREG(SDNode *N);
308309
SDValue PromoteIntRes_INSERT_VECTOR_ELT(SDNode *N);
309310
SDValue PromoteIntRes_CONCAT_VECTORS(SDNode *N);
@@ -836,6 +837,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
836837
void SplitVecRes_MLOAD(MaskedLoadSDNode *MLD, SDValue &Lo, SDValue &Hi);
837838
void SplitVecRes_MGATHER(MaskedGatherSDNode *MGT, SDValue &Lo, SDValue &Hi);
838839
void SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo, SDValue &Hi);
840+
void SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi);
839841
void SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi);
840842
void SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo, SDValue &Hi);
841843
void SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, SDValue &Lo,

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,9 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
928928
case ISD::SCALAR_TO_VECTOR:
929929
SplitVecRes_ScalarOp(N, Lo, Hi);
930930
break;
931+
case ISD::STEP_VECTOR:
932+
SplitVecRes_STEP_VECTOR(N, Lo, Hi);
933+
break;
931934
case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
932935
case ISD::LOAD:
933936
SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
@@ -1639,6 +1642,30 @@ void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
16391642
Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
16401643
}
16411644

1645+
void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
1646+
SDValue &Hi) {
1647+
EVT LoVT, HiVT;
1648+
SDLoc dl(N);
1649+
assert(N->getValueType(0).isScalableVector() &&
1650+
"Only scalable vectors are supported for STEP_VECTOR");
1651+
std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
1652+
SDValue Step = N->getOperand(0);
1653+
1654+
Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);
1655+
1656+
// Hi = Lo + (EltCnt * Step)
1657+
EVT EltVT = Step.getValueType();
1658+
SDValue StartOfHi =
1659+
DAG.getVScale(dl, EltVT,
1660+
cast<ConstantSDNode>(Step)->getAPIntValue() *
1661+
LoVT.getVectorMinNumElements());
1662+
StartOfHi = DAG.getZExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
1663+
StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);
1664+
1665+
Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
1666+
Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
1667+
}
1668+
16421669
void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
16431670
SDValue &Hi) {
16441671
EVT LoVT, HiVT;

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,18 @@ SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) {
17441744
return SDValue(CondCodeNodes[Cond], 0);
17451745
}
17461746

1747+
SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT, SDValue Step) {
1748+
if (ResVT.isScalableVector())
1749+
return getNode(ISD::STEP_VECTOR, DL, ResVT, Step);
1750+
1751+
EVT OpVT = Step.getValueType();
1752+
APInt StepVal = cast<ConstantSDNode>(Step)->getAPIntValue();
1753+
SmallVector<SDValue, 16> OpsStepConstants;
1754+
for (uint64_t i = 0; i < ResVT.getVectorNumElements(); i++)
1755+
OpsStepConstants.push_back(getConstant(StepVal * i, DL, OpVT));
1756+
return getBuildVector(ResVT, DL, OpsStepConstants);
1757+
}
1758+
17471759
/// Swaps the values of N1 and N2. Swaps all indices in the shuffle mask M that
17481760
/// point at N1 to point at N2 and indices that point at N2 to point at N1.
17491761
static void commuteShuffle(SDValue &N1, SDValue &N2, MutableArrayRef<int> M) {
@@ -4339,6 +4351,14 @@ bool SelectionDAG::haveNoCommonBitsSet(SDValue A, SDValue B) const {
43394351
return (computeKnownBits(A).Zero | computeKnownBits(B).Zero).isAllOnesValue();
43404352
}
43414353

4354+
static SDValue FoldSTEP_VECTOR(const SDLoc &DL, EVT VT, SDValue Step,
4355+
SelectionDAG &DAG) {
4356+
if (cast<ConstantSDNode>(Step)->isNullValue())
4357+
return DAG.getConstant(0, DL, VT);
4358+
4359+
return SDValue();
4360+
}
4361+
43424362
static SDValue FoldBUILD_VECTOR(const SDLoc &DL, EVT VT,
43434363
ArrayRef<SDValue> Ops,
43444364
SelectionDAG &DAG) {
@@ -4560,6 +4580,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
45604580
APFloat::rmNearestTiesToEven, &Ignored);
45614581
return getConstantFP(FPV, DL, VT);
45624582
}
4583+
case ISD::STEP_VECTOR: {
4584+
if (SDValue V = FoldSTEP_VECTOR(DL, VT, Operand, *this))
4585+
return V;
4586+
break;
4587+
}
45634588
}
45644589
}
45654590

@@ -4669,6 +4694,18 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
46694694

46704695
unsigned OpOpcode = Operand.getNode()->getOpcode();
46714696
switch (Opcode) {
4697+
case ISD::STEP_VECTOR:
4698+
assert(VT.isScalableVector() &&
4699+
"STEP_VECTOR can only be used with scalable types");
4700+
assert(VT.getScalarSizeInBits() >= 8 &&
4701+
"STEP_VECTOR can only be used with vectors of integers that are at "
4702+
"least 8 bits wide");
4703+
assert(Operand.getValueType().bitsGE(VT.getScalarType()) &&
4704+
"Operand type should be at least as large as the element type");
4705+
assert(isa<ConstantSDNode>(Operand) &&
4706+
cast<ConstantSDNode>(Operand)->getAPIntValue().isNonNegative() &&
4707+
"Expected positive integer constant for STEP_VECTOR");
4708+
break;
46724709
case ISD::FREEZE:
46734710
assert(VT == Operand.getValueType() && "Unexpected VT!");
46744711
break;

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6945,7 +6945,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
69456945
case Intrinsic::experimental_deoptimize:
69466946
LowerDeoptimizeCall(&I);
69476947
return;
6948-
6948+
case Intrinsic::experimental_stepvector:
6949+
visitStepVector(I);
6950+
return;
69496951
case Intrinsic::vector_reduce_fadd:
69506952
case Intrinsic::vector_reduce_fmul:
69516953
case Intrinsic::vector_reduce_add:
@@ -10929,6 +10931,16 @@ void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) {
1092910931
}
1093010932
}
1093110933

10934+
void SelectionDAGBuilder::visitStepVector(const CallInst &I) {
10935+
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
10936+
auto DL = getCurSDLoc();
10937+
EVT ResultVT = TLI.getValueType(DAG.getDataLayout(), I.getType());
10938+
EVT OpVT =
10939+
TLI.getTypeToTransformTo(*DAG.getContext(), ResultVT.getScalarType());
10940+
SDValue Step = DAG.getConstant(1, DL, OpVT);
10941+
setValue(&I, DAG.getStepVector(DL, ResultVT, Step));
10942+
}
10943+
1093210944
void SelectionDAGBuilder::visitVectorReverse(const CallInst &I) {
1093310945
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1093410946
EVT VT = TLI.getValueType(DAG.getDataLayout(), I.getType());

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ class SelectionDAGBuilder {
779779
void visitVectorReduce(const CallInst &I, unsigned Intrinsic);
780780
void visitVectorReverse(const CallInst &I);
781781
void visitVectorSplice(const CallInst &I);
782+
void visitStepVector(const CallInst &I);
782783

783784
void visitUserOp1(const Instruction &I) {
784785
llvm_unreachable("UserOp1 should not exist at instruction selection time!");

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
292292
case ISD::SPLAT_VECTOR: return "splat_vector";
293293
case ISD::SPLAT_VECTOR_PARTS: return "splat_vector_parts";
294294
case ISD::VECTOR_REVERSE: return "vector_reverse";
295+
case ISD::STEP_VECTOR: return "step_vector";
295296
case ISD::CARRY_FALSE: return "carry_false";
296297
case ISD::ADDC: return "addc";
297298
case ISD::ADDE: return "adde";

llvm/lib/IR/IRBuilder.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,23 @@ Value *IRBuilderBase::CreateVScale(Constant *Scaling, const Twine &Name) {
9191
: CreateMul(CI, Scaling);
9292
}
9393

94+
Value *IRBuilderBase::CreateStepVector(Type *DstType, const Twine &Name) {
95+
if (isa<ScalableVectorType>(DstType))
96+
return CreateIntrinsic(Intrinsic::experimental_stepvector, {DstType}, {},
97+
nullptr, Name);
98+
99+
Type *STy = DstType->getScalarType();
100+
unsigned NumEls = cast<FixedVectorType>(DstType)->getNumElements();
101+
102+
// Create a vector of consecutive numbers from zero to VF.
103+
SmallVector<Constant *, 8> Indices;
104+
for (unsigned i = 0; i < NumEls; ++i)
105+
Indices.push_back(ConstantInt::get(STy, i));
106+
107+
// Add the consecutive indices to the vector value.
108+
return ConstantVector::get(Indices);
109+
}
110+
94111
CallInst *IRBuilderBase::CreateMemSet(Value *Ptr, Value *Val, Value *Size,
95112
MaybeAlign Align, bool isVolatile,
96113
MDNode *TBAATag, MDNode *ScopeTag,

llvm/lib/IR/Verifier.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5195,6 +5195,15 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
51955195

51965196
break;
51975197
}
5198+
case Intrinsic::experimental_stepvector: {
5199+
VectorType *VecTy = dyn_cast<VectorType>(Call.getType());
5200+
Assert(VecTy && VecTy->getScalarType()->isIntegerTy() &&
5201+
VecTy->getScalarSizeInBits() >= 8,
5202+
"experimental_stepvector only supported for vectors of integers "
5203+
"with a bitwidth of at least 8.",
5204+
&Call);
5205+
break;
5206+
}
51985207
case Intrinsic::experimental_vector_insert: {
51995208
VectorType *VecTy = cast<VectorType>(Call.getArgOperand(0)->getType());
52005209
VectorType *SubVecTy = cast<VectorType>(Call.getArgOperand(1)->getType());

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
11351135
setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom);
11361136
setOperationAction(ISD::VECREDUCE_SMIN, VT, Custom);
11371137
setOperationAction(ISD::VECREDUCE_SMAX, VT, Custom);
1138+
setOperationAction(ISD::STEP_VECTOR, VT, Custom);
11381139

11391140
setOperationAction(ISD::MULHU, VT, Expand);
11401141
setOperationAction(ISD::MULHS, VT, Expand);
@@ -4402,6 +4403,8 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
44024403
return LowerVECTOR_SHUFFLE(Op, DAG);
44034404
case ISD::SPLAT_VECTOR:
44044405
return LowerSPLAT_VECTOR(Op, DAG);
4406+
case ISD::STEP_VECTOR:
4407+
return LowerSTEP_VECTOR(Op, DAG);
44054408
case ISD::EXTRACT_SUBVECTOR:
44064409
return LowerEXTRACT_SUBVECTOR(Op, DAG);
44074410
case ISD::INSERT_SUBVECTOR:
@@ -9049,6 +9052,21 @@ SDValue AArch64TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
90499052
return GenerateTBL(Op, ShuffleMask, DAG);
90509053
}
90519054

9055+
SDValue AArch64TargetLowering::LowerSTEP_VECTOR(SDValue Op,
9056+
SelectionDAG &DAG) const {
9057+
SDLoc dl(Op);
9058+
EVT VT = Op.getValueType();
9059+
assert(VT.isScalableVector() &&
9060+
"Only expect scalable vectors for STEP_VECTOR");
9061+
EVT ElemVT = VT.getScalarType();
9062+
assert(ElemVT != MVT::i1 &&
9063+
"Vectors of i1 types not supported for STEP_VECTOR");
9064+
9065+
SDValue StepVal = Op.getOperand(0);
9066+
SDValue Zero = DAG.getConstant(0, dl, StepVal.getValueType());
9067+
return DAG.getNode(AArch64ISD::INDEX_VECTOR, dl, VT, Zero, StepVal);
9068+
}
9069+
90529070
SDValue AArch64TargetLowering::LowerSPLAT_VECTOR(SDValue Op,
90539071
SelectionDAG &DAG) const {
90549072
SDLoc dl(Op);

llvm/lib/Target/AArch64/AArch64ISelLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,7 @@ class AArch64TargetLowering : public TargetLowering {
936936
SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const;
937937
SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
938938
SDValue LowerSPLAT_VECTOR(SDValue Op, SelectionDAG &DAG) const;
939+
SDValue LowerSTEP_VECTOR(SDValue Op, SelectionDAG &DAG) const;
939940
SDValue LowerDUPQLane(SDValue Op, SelectionDAG &DAG) const;
940941
SDValue LowerToPredicatedOp(SDValue Op, SelectionDAG &DAG, unsigned NewOp,
941942
bool OverrideNEON = false) const;

0 commit comments

Comments
 (0)