[llvm] [RISCV] Handle fixed length vectors with exact VLEN in loweringEXTRACT_SUBVECTOR (PR #79949)
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 12 08:25:32 PST 2024
================
@@ -9653,19 +9656,46 @@ SDValue RISCVTargetLowering::lowerEXTRACT_SUBVECTOR(SDValue Op,
return DAG.getBitcast(Op.getValueType(), Slidedown);
}
+ if (VecVT.isFixedLengthVector()) {
+ VecVT = getContainerForFixedLengthVector(VecVT);
+ Vec = convertToScalableVector(VecVT, Vec, DAG, Subtarget);
+ }
+
+ MVT ContainerSubVecVT = SubVecVT;
unsigned SubRegIdx, RemIdx;
- std::tie(SubRegIdx, RemIdx) =
- RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs(
- VecVT, SubVecVT, OrigIdx, TRI);
+
+ // extract_subvector scales the index by vscale is the subvector is scalable,
+ // and decomposeSubvectorInsertExtractToSubRegs takes this into account. So if
+ // we have a fixed length subvector, we need to adjust the index by 1/vscale.
+ if (SubVecVT.isFixedLengthVector()) {
+ assert(MinVLen == MaxVLen);
+ ContainerSubVecVT = getContainerForFixedLengthVector(SubVecVT);
+ unsigned Vscale = MinVLen / RISCV::RVVBitsPerBlock;
+ std::tie(SubRegIdx, RemIdx) =
+ RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs(
+ VecVT, ContainerSubVecVT, OrigIdx / Vscale, TRI);
+ RemIdx = (RemIdx * Vscale) + (OrigIdx % Vscale);
+ } else {
+ std::tie(SubRegIdx, RemIdx) =
+ RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs(
+ VecVT, ContainerSubVecVT, OrigIdx, TRI);
+ }
// If the Idx has been completely eliminated then this is a subvector extract
// which naturally aligns to a vector register. These can easily be handled
// using subregister manipulation.
- if (RemIdx == 0)
+ if (RemIdx == 0) {
+ if (SubVecVT.isFixedLengthVector()) {
+ Vec = DAG.getTargetExtractSubreg(SubRegIdx, DL, ContainerSubVecVT, Vec);
+ return convertFromScalableVector(SubVecVT, Vec, DAG, Subtarget);
+ }
return Op;
+ }
- // Else SubVecVT is a fractional LMUL and may need to be slid down.
- assert(RISCVVType::decodeVLMUL(getLMUL(SubVecVT)).second);
+ // Else SubVecVT is a fractional LMUL and may need to be slid down: if
+ // SubVecVT was > M1 then the index would need to be a multiple of VLMAX, and
+ // so would divide exactly.
+ assert(RISCVVType::decodeVLMUL(getLMUL(ContainerSubVecVT)).second);
// If the vector type is an LMUL-group type, extract a subvector equal to the
// nearest full vector register type.
----------------
preames wrote:
Yep, that was what I'd forgotten. Basically, for scalable, we can't end up with an m1 or larger subvec type because if we had, we'd have had RemIdx = 0 and exited above. (Since there is no such thing as a m1.5 or a m1 offset halfway through a reg.)
https://github.com/llvm/llvm-project/pull/79949
More information about the llvm-commits
mailing list