Skip to content

Commit e223af2

Browse files
committed
[RISCV] Emit VP strided loads/stores in RISCVGatherScatterLowering
RISCVGatherScatterLowering is the last user of riscv_masked_strided_{load,store} after #98131 and #98112, this patch changes it to emit the VP equivalent instead. This allows us to remove the masked_strided intrinsics so we have only have one lowering path. riscv_masked_strided_{load,store} didn't have AVL operands and were always VLMAX, so this passes in the fixed or scalable element count to the EVL instead, which RISCVVectorPeephole should now convert to VLMAX after #97800
1 parent 563ae62 commit e223af2

File tree

8 files changed

+115
-387
lines changed

8 files changed

+115
-387
lines changed

llvm/include/llvm/IR/IntrinsicsRISCV.td

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,20 +1710,6 @@ let TargetPrefix = "riscv" in {
17101710
defm vsuxseg # nf : RISCVISegStore<nf>;
17111711
}
17121712

1713-
// Strided loads/stores for fixed vectors.
1714-
def int_riscv_masked_strided_load
1715-
: DefaultAttrsIntrinsic<[llvm_anyvector_ty],
1716-
[LLVMMatchType<0>, llvm_anyptr_ty,
1717-
llvm_anyint_ty,
1718-
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
1719-
[NoCapture<ArgIndex<1>>, IntrReadMem]>;
1720-
def int_riscv_masked_strided_store
1721-
: DefaultAttrsIntrinsic<[],
1722-
[llvm_anyvector_ty, llvm_anyptr_ty,
1723-
llvm_anyint_ty,
1724-
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
1725-
[NoCapture<ArgIndex<1>>, IntrWriteMem]>;
1726-
17271713
// Segment loads/stores for fixed vectors.
17281714
foreach nf = [2, 3, 4, 5, 6, 7, 8] in {
17291715
def int_riscv_seg # nf # _load

llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -515,17 +515,23 @@ bool RISCVGatherScatterLowering::tryCreateStridedLoadStore(IntrinsicInst *II,
515515

516516
Builder.SetInsertPoint(II);
517517

518+
Value *EVL = Builder.CreateElementCount(
519+
IntegerType::get(Ctx, 32), cast<VectorType>(DataType)->getElementCount());
520+
518521
CallInst *Call;
519-
if (II->getIntrinsicID() == Intrinsic::masked_gather)
522+
if (II->getIntrinsicID() == Intrinsic::masked_gather) {
520523
Call = Builder.CreateIntrinsic(
521-
Intrinsic::riscv_masked_strided_load,
524+
Intrinsic::experimental_vp_strided_load,
522525
{DataType, BasePtr->getType(), Stride->getType()},
523-
{II->getArgOperand(3), BasePtr, Stride, II->getArgOperand(2)});
524-
else
526+
{BasePtr, Stride, II->getArgOperand(2), EVL});
527+
Call = Builder.CreateIntrinsic(
528+
Intrinsic::vp_select, {DataType},
529+
{II->getOperand(2), Call, II->getArgOperand(3), EVL});
530+
} else
525531
Call = Builder.CreateIntrinsic(
526-
Intrinsic::riscv_masked_strided_store,
532+
Intrinsic::experimental_vp_strided_store,
527533
{DataType, BasePtr->getType(), Stride->getType()},
528-
{II->getArgOperand(0), BasePtr, Stride, II->getArgOperand(3)});
534+
{II->getArgOperand(0), BasePtr, Stride, II->getArgOperand(3), EVL});
529535

530536
Call->takeName(II);
531537
II->replaceAllUsesWith(Call);

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 0 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,12 +1621,6 @@ bool RISCVTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
16211621
Info.flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore |
16221622
MachineMemOperand::MOVolatile;
16231623
return true;
1624-
case Intrinsic::riscv_masked_strided_load:
1625-
return SetRVVLoadStoreInfo(/*PtrOp*/ 1, /*IsStore*/ false,
1626-
/*IsUnitStrided*/ false);
1627-
case Intrinsic::riscv_masked_strided_store:
1628-
return SetRVVLoadStoreInfo(/*PtrOp*/ 1, /*IsStore*/ true,
1629-
/*IsUnitStrided*/ false);
16301624
case Intrinsic::riscv_seg2_load:
16311625
case Intrinsic::riscv_seg3_load:
16321626
case Intrinsic::riscv_seg4_load:
@@ -9401,81 +9395,6 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
94019395
switch (IntNo) {
94029396
default:
94039397
break;
9404-
case Intrinsic::riscv_masked_strided_load: {
9405-
SDLoc DL(Op);
9406-
MVT XLenVT = Subtarget.getXLenVT();
9407-
9408-
// If the mask is known to be all ones, optimize to an unmasked intrinsic;
9409-
// the selection of the masked intrinsics doesn't do this for us.
9410-
SDValue Mask = Op.getOperand(5);
9411-
bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode());
9412-
9413-
MVT VT = Op->getSimpleValueType(0);
9414-
MVT ContainerVT = VT;
9415-
if (VT.isFixedLengthVector())
9416-
ContainerVT = getContainerForFixedLengthVector(VT);
9417-
9418-
SDValue PassThru = Op.getOperand(2);
9419-
if (!IsUnmasked) {
9420-
MVT MaskVT = getMaskTypeFor(ContainerVT);
9421-
if (VT.isFixedLengthVector()) {
9422-
Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
9423-
PassThru = convertToScalableVector(ContainerVT, PassThru, DAG, Subtarget);
9424-
}
9425-
}
9426-
9427-
auto *Load = cast<MemIntrinsicSDNode>(Op);
9428-
SDValue VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
9429-
SDValue Ptr = Op.getOperand(3);
9430-
SDValue Stride = Op.getOperand(4);
9431-
SDValue Result, Chain;
9432-
9433-
// TODO: We restrict this to unmasked loads currently in consideration of
9434-
// the complexity of handling all falses masks.
9435-
MVT ScalarVT = ContainerVT.getVectorElementType();
9436-
if (IsUnmasked && isNullConstant(Stride) && ContainerVT.isInteger()) {
9437-
SDValue ScalarLoad =
9438-
DAG.getExtLoad(ISD::EXTLOAD, DL, XLenVT, Load->getChain(), Ptr,
9439-
ScalarVT, Load->getMemOperand());
9440-
Chain = ScalarLoad.getValue(1);
9441-
Result = lowerScalarSplat(SDValue(), ScalarLoad, VL, ContainerVT, DL, DAG,
9442-
Subtarget);
9443-
} else if (IsUnmasked && isNullConstant(Stride) && isTypeLegal(ScalarVT)) {
9444-
SDValue ScalarLoad = DAG.getLoad(ScalarVT, DL, Load->getChain(), Ptr,
9445-
Load->getMemOperand());
9446-
Chain = ScalarLoad.getValue(1);
9447-
Result = DAG.getSplat(ContainerVT, DL, ScalarLoad);
9448-
} else {
9449-
SDValue IntID = DAG.getTargetConstant(
9450-
IsUnmasked ? Intrinsic::riscv_vlse : Intrinsic::riscv_vlse_mask, DL,
9451-
XLenVT);
9452-
9453-
SmallVector<SDValue, 8> Ops{Load->getChain(), IntID};
9454-
if (IsUnmasked)
9455-
Ops.push_back(DAG.getUNDEF(ContainerVT));
9456-
else
9457-
Ops.push_back(PassThru);
9458-
Ops.push_back(Ptr);
9459-
Ops.push_back(Stride);
9460-
if (!IsUnmasked)
9461-
Ops.push_back(Mask);
9462-
Ops.push_back(VL);
9463-
if (!IsUnmasked) {
9464-
SDValue Policy =
9465-
DAG.getTargetConstant(RISCVII::TAIL_AGNOSTIC, DL, XLenVT);
9466-
Ops.push_back(Policy);
9467-
}
9468-
9469-
SDVTList VTs = DAG.getVTList({ContainerVT, MVT::Other});
9470-
Result =
9471-
DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, VTs, Ops,
9472-
Load->getMemoryVT(), Load->getMemOperand());
9473-
Chain = Result.getValue(1);
9474-
}
9475-
if (VT.isFixedLengthVector())
9476-
Result = convertFromScalableVector(VT, Result, DAG, Subtarget);
9477-
return DAG.getMergeValues({Result, Chain}, DL);
9478-
}
94799398
case Intrinsic::riscv_seg2_load:
94809399
case Intrinsic::riscv_seg3_load:
94819400
case Intrinsic::riscv_seg4_load:
@@ -9555,47 +9474,6 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_VOID(SDValue Op,
95559474
switch (IntNo) {
95569475
default:
95579476
break;
9558-
case Intrinsic::riscv_masked_strided_store: {
9559-
SDLoc DL(Op);
9560-
MVT XLenVT = Subtarget.getXLenVT();
9561-
9562-
// If the mask is known to be all ones, optimize to an unmasked intrinsic;
9563-
// the selection of the masked intrinsics doesn't do this for us.
9564-
SDValue Mask = Op.getOperand(5);
9565-
bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode());
9566-
9567-
SDValue Val = Op.getOperand(2);
9568-
MVT VT = Val.getSimpleValueType();
9569-
MVT ContainerVT = VT;
9570-
if (VT.isFixedLengthVector()) {
9571-
ContainerVT = getContainerForFixedLengthVector(VT);
9572-
Val = convertToScalableVector(ContainerVT, Val, DAG, Subtarget);
9573-
}
9574-
if (!IsUnmasked) {
9575-
MVT MaskVT = getMaskTypeFor(ContainerVT);
9576-
if (VT.isFixedLengthVector())
9577-
Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
9578-
}
9579-
9580-
SDValue VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second;
9581-
9582-
SDValue IntID = DAG.getTargetConstant(
9583-
IsUnmasked ? Intrinsic::riscv_vsse : Intrinsic::riscv_vsse_mask, DL,
9584-
XLenVT);
9585-
9586-
auto *Store = cast<MemIntrinsicSDNode>(Op);
9587-
SmallVector<SDValue, 8> Ops{Store->getChain(), IntID};
9588-
Ops.push_back(Val);
9589-
Ops.push_back(Op.getOperand(3)); // Ptr
9590-
Ops.push_back(Op.getOperand(4)); // Stride
9591-
if (!IsUnmasked)
9592-
Ops.push_back(Mask);
9593-
Ops.push_back(VL);
9594-
9595-
return DAG.getMemIntrinsicNode(ISD::INTRINSIC_VOID, DL, Store->getVTList(),
9596-
Ops, Store->getMemoryVT(),
9597-
Store->getMemOperand());
9598-
}
95999477
case Intrinsic::riscv_seg2_store:
96009478
case Intrinsic::riscv_seg3_store:
96019479
case Intrinsic::riscv_seg4_store:
@@ -17509,43 +17387,6 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
1750917387
// By default we do not combine any intrinsic.
1751017388
default:
1751117389
return SDValue();
17512-
case Intrinsic::riscv_masked_strided_load: {
17513-
MVT VT = N->getSimpleValueType(0);
17514-
auto *Load = cast<MemIntrinsicSDNode>(N);
17515-
SDValue PassThru = N->getOperand(2);
17516-
SDValue Base = N->getOperand(3);
17517-
SDValue Stride = N->getOperand(4);
17518-
SDValue Mask = N->getOperand(5);
17519-
17520-
// If the stride is equal to the element size in bytes, we can use
17521-
// a masked.load.
17522-
const unsigned ElementSize = VT.getScalarStoreSize();
17523-
if (auto *StrideC = dyn_cast<ConstantSDNode>(Stride);
17524-
StrideC && StrideC->getZExtValue() == ElementSize)
17525-
return DAG.getMaskedLoad(VT, DL, Load->getChain(), Base,
17526-
DAG.getUNDEF(XLenVT), Mask, PassThru,
17527-
Load->getMemoryVT(), Load->getMemOperand(),
17528-
ISD::UNINDEXED, ISD::NON_EXTLOAD);
17529-
return SDValue();
17530-
}
17531-
case Intrinsic::riscv_masked_strided_store: {
17532-
auto *Store = cast<MemIntrinsicSDNode>(N);
17533-
SDValue Value = N->getOperand(2);
17534-
SDValue Base = N->getOperand(3);
17535-
SDValue Stride = N->getOperand(4);
17536-
SDValue Mask = N->getOperand(5);
17537-
17538-
// If the stride is equal to the element size in bytes, we can use
17539-
// a masked.store.
17540-
const unsigned ElementSize = Value.getValueType().getScalarStoreSize();
17541-
if (auto *StrideC = dyn_cast<ConstantSDNode>(Stride);
17542-
StrideC && StrideC->getZExtValue() == ElementSize)
17543-
return DAG.getMaskedStore(Store->getChain(), DL, Value, Base,
17544-
DAG.getUNDEF(XLenVT), Mask,
17545-
Value.getValueType(), Store->getMemOperand(),
17546-
ISD::UNINDEXED, false);
17547-
return SDValue();
17548-
}
1754917390
case Intrinsic::riscv_vcpop:
1755017391
case Intrinsic::riscv_vcpop_mask:
1755117392
case Intrinsic::riscv_vfirst:

llvm/test/CodeGen/RISCV/pr89833.ll

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)