Skip to content

[RISCV] Allow non-power-of-2 vectors for VLS code generation #97010

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 2 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
425 changes: 224 additions & 201 deletions llvm/include/llvm/CodeGen/ValueTypes.td

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM,
setTruncStoreAction(MVT::v2f64, MVT::v2f16, Expand);

setTruncStoreAction(MVT::v3i32, MVT::v3i8, Expand);
setTruncStoreAction(MVT::v5i32, MVT::v5i8, Expand);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems suspicious we don't need a v5i32->v5i16 case. Probably missing test coverage


setTruncStoreAction(MVT::v3i64, MVT::v3i32, Expand);
setTruncStoreAction(MVT::v3i64, MVT::v3i16, Expand);
Expand Down Expand Up @@ -1194,7 +1195,7 @@ void AMDGPUTargetLowering::analyzeFormalArgumentsCompute(

if (NumRegs == 1) {
// This argument is not split, so the IR type is the memory type.
if (ArgVT.isExtended()) {
if (ArgVT.isExtended() || (ArgVT.isVector() && !ArgVT.isPow2VectorType())) {
// We have an extended type, like i24, so we should just use the
// register type.
MemVT = RegisterVT;
Expand Down
2 changes: 0 additions & 2 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2259,8 +2259,6 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
[[maybe_unused]] bool ExactlyVecRegSized =
Subtarget->expandVScale(SubVecVT.getSizeInBits())
.isKnownMultipleOf(Subtarget->expandVScale(VecRegSize));
assert(isPowerOf2_64(Subtarget->expandVScale(SubVecVT.getSizeInBits())
.getKnownMinValue()));
assert(Idx == 0 && (ExactlyVecRegSized || V.isUndef()));
}
MVT ContainerVT = VT;
Expand Down
39 changes: 30 additions & 9 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2584,9 +2584,14 @@ static bool useRVVForFixedLengthVectorVT(MVT VT,
if (LMul > Subtarget.getMaxLMULForFixedLengthVectors())
return false;

// TODO: Perhaps an artificial restriction, but worth having whilst getting
// the base fixed length RVV support in place.
if (!VT.isPow2VectorType())
// Only support non-power-of-2 fixed length vector types with lengths 3, 5, 7,
// or 15.
// In theory, we could support any length, but we want to prevent the
// number of MVTs from growing too quickly. Therefore, we only add these
// specific types.
unsigned NumElems = VT.getVectorNumElements();
if (!VT.isPow2VectorType() && NumElems != 3 && NumElems != 5 &&
NumElems != 7 && NumElems != 15)
return false;

return true;
Expand Down Expand Up @@ -2623,10 +2628,14 @@ static MVT getContainerForFixedLengthVector(const TargetLowering &TLI, MVT VT,
// We prefer to use LMUL=1 for VLEN sized types. Use fractional lmuls for
// narrower types. The smallest fractional LMUL we support is 8/ELEN. Within
// each fractional LMUL we support SEW between 8 and LMUL*ELEN.
unsigned NumVLSElts = VT.getVectorNumElements();
if (!isPowerOf2_32(NumVLSElts))
NumVLSElts = llvm::NextPowerOf2 (NumVLSElts);

unsigned NumElts =
(VT.getVectorNumElements() * RISCV::RVVBitsPerBlock) / MinVLen;
(NumVLSElts * RISCV::RVVBitsPerBlock) / MinVLen;
NumElts = std::max(NumElts, RISCV::RVVBitsPerBlock / MaxELen);
assert(isPowerOf2_32(NumElts) && "Expected power of 2 NumElts");

return MVT::getScalableVectorVT(EltVT, NumElts);
}
}
Expand Down Expand Up @@ -3573,6 +3582,8 @@ static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG,
// XLenVT if we're producing a v8i1. This results in more consistent
// codegen across RV32 and RV64.
unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.getXLen());
if (!isPowerOf2_32(NumViaIntegerBits))
NumViaIntegerBits = llvm::NextPowerOf2 (NumViaIntegerBits);
NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.getELen());
// If we have to use more than one INSERT_VECTOR_ELT then this
// optimization is likely to increase code size; avoid peforming it in
Expand Down Expand Up @@ -3616,10 +3627,16 @@ static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG,
// If we're producing a smaller vector than our minimum legal integer
// type, bitcast to the equivalent (known-legal) mask type, and extract
// our final mask.
assert(IntegerViaVecVT == MVT::v1i8 && "Unexpected mask vector type");
Vec = DAG.getBitcast(MVT::v8i1, Vec);
Vec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Vec,
DAG.getConstant(0, DL, XLenVT));
if (IntegerViaVecVT == MVT::v1i8){
assert(IntegerViaVecVT == MVT::v1i8 && "Unexpected mask vector type");
Vec = DAG.getBitcast(MVT::v8i1, Vec);
Vec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Vec,
DAG.getConstant(0, DL, XLenVT));
} else if (IntegerViaVecVT == MVT::v1i16) {
Vec = DAG.getBitcast(MVT::v16i1, Vec);
Vec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Vec,
DAG.getConstant(0, DL, XLenVT));
}
} else {
// Else we must have produced an integer type with the same size as the
// mask type; bitcast for the final result.
Expand Down Expand Up @@ -4873,6 +4890,10 @@ static bool isLegalBitRotate(ShuffleVectorSDNode *SVN,

EVT VT = SVN->getValueType(0);
unsigned NumElts = VT.getVectorNumElements();
// We don't handle non-power-of-2 here.
if (!isPowerOf2_32(NumElts))
return false;

unsigned EltSizeInBits = VT.getScalarSizeInBits();
unsigned NumSubElts;
if (!ShuffleVectorInst::isBitRotateMask(SVN->getMask(), EltSizeInBits, 2,
Expand Down
Loading
Loading