[llvm] [AArch64][SVE] Support lowering fixed-length BUILD_VECTORS to ZIPs (PR #111698)
Sander de Smalen via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 10 00:18:46 PDT 2024
================
@@ -14384,24 +14385,67 @@ static SDValue ConstantBuildVector(SDValue Op, SelectionDAG &DAG,
return SDValue();
}
-SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op,
- SelectionDAG &DAG) const {
+SDValue AArch64TargetLowering::LowerFixedLengthBuildVectorToSVE(
+ SDValue Op, SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
+ SDLoc DL(Op);
+ EVT ContainerVT = getContainerForFixedLengthVector(DAG, VT);
+ auto *BVN = cast<BuildVectorSDNode>(Op);
- if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable())) {
- if (auto SeqInfo = cast<BuildVectorSDNode>(Op)->isConstantSequence()) {
- SDLoc DL(Op);
- EVT ContainerVT = getContainerForFixedLengthVector(DAG, VT);
- SDValue Start = DAG.getConstant(SeqInfo->first, DL, ContainerVT);
- SDValue Steps = DAG.getStepVector(DL, ContainerVT, SeqInfo->second);
- SDValue Seq = DAG.getNode(ISD::ADD, DL, ContainerVT, Start, Steps);
- return convertFromScalableVector(DAG, Op.getValueType(), Seq);
- }
+ if (auto SeqInfo = BVN->isConstantSequence()) {
+ SDValue Start = DAG.getConstant(SeqInfo->first, DL, ContainerVT);
+ SDValue Steps = DAG.getStepVector(DL, ContainerVT, SeqInfo->second);
+ SDValue Seq = DAG.getNode(ISD::ADD, DL, ContainerVT, Start, Steps);
+ return convertFromScalableVector(DAG, VT, Seq);
+ }
- // Revert to common legalisation for all other variants.
+ if (!VT.isPow2VectorType() || VT.getFixedSizeInBits() > 128 ||
+ VT.getVectorNumElements() <= 1 || BVN->isConstant())
return SDValue();
+
+ // Lower (pow2) BUILD_VECTORS that are <= 128-bit to a sequence of ZIP1s.
+ EVT ZipVT = ContainerVT;
+ SDValue ZeroI64 = DAG.getConstant(0, DL, MVT::i64);
+ SmallVector<SDValue, 16> Intermediates =
+ llvm::map_to_vector<16>(Op->op_values(), [&](SDValue Op) {
+ SDValue Undef = DAG.getUNDEF(ZipVT);
+ return Op.isUndef() ? Undef
+ : DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ZipVT,
+ Undef, Op, ZeroI64);
+ });
+
+ while (Intermediates.size() > 1) {
+ auto ToZipVT = [&](SDValue Op) { return DAG.getBitcast(ZipVT, Op); };
+ for (unsigned I = 0; I < Intermediates.size(); I += 2) {
+ SDValue Op0 = Intermediates[I + 0];
+ SDValue Op1 = Intermediates[I + 1];
+ Intermediates[I / 2] = Op1.isUndef()
+ ? Op0
+ : DAG.getNode(AArch64ISD::ZIP1, DL, ZipVT,
+ ToZipVT(Op0), ToZipVT(Op1));
+ }
----------------
sdesmalen-arm wrote:
nit:
```suggestion
for (unsigned I = 0; I < Intermediates.size(); I += 2) {
SDValue Op0 = DAG.getBitcast(ZipVT, Intermediates[I + 0]);
SDValue Op1 = DAG.getBitcast(ZipVT, Intermediates[I + 1]);
Intermediates[I / 2] =
Op1.isUndef() ? Op0
: DAG.getNode(AArch64ISD::ZIP1, DL, ZipVT, Op0, Op1);
}
```
https://github.com/llvm/llvm-project/pull/111698
More information about the llvm-commits
mailing list