diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -734,6 +734,18 @@ bool fallBackToDAGISel(const Instruction &Inst) const override; + bool + shouldExpandBuildVectorWithShuffles(EVT VT, + unsigned DefinedValues) const override; + + /// SVE code generation for fixed length vectors does not custom lower + /// BUILD_VECTOR. This makes BUILD_VECTOR legalisation a source of stores to + /// merge. However, merging them creates a BUILD_VECTOR that is just as + /// illegal as the original, thus leading to an infinite legalisation loop. + bool mergeStoresAfterLegalization(EVT VT) const override { + return !useSVEForFixedLengthVectors(); + } + private: /// Keep a pointer to the AArch64Subtarget around so that we can /// make the right decision when generating code for different targets. diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3564,6 +3564,16 @@ } } +// VECTOR_SHUFFLE is not legal for vectors bigger than NEON, so we cannot use +// them to expand BUILD_VECTOR. +bool AArch64TargetLowering::shouldExpandBuildVectorWithShuffles( + EVT VT, unsigned DefinedValues) const { + if (useSVEForFixedLengthVectorVT(VT)) + return false; + + return TargetLowering::shouldExpandBuildVectorWithShuffles(VT, DefinedValues); +} + bool AArch64TargetLowering::useSVEForFixedLengthVectors() const { // Prefer NEON unless larger SVE registers are available. return Subtarget->hasSVE() && Subtarget->getMinSVEVectorSizeInBits() >= 256; diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll b/llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll --- a/llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll +++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-shuffles.ll @@ -3,6 +3,18 @@ target triple = "aarch64-unknown-linux-gnu" +; Currently there is no custom lowering for vector shuffles operating on types +; bigger than NEON. However, having no support opens us up to a code generator +; hang when expanding BUILD_VECTOR. Here we just validate the promblematic case +; successfully exits code generation. +define void @hang_when_merging_stores_after_legalisation(<8 x i32>* %a, <2 x i32> %b) #0 { +; CHECK-LABEL: hang_when_merging_stores_after_legalisation: + %splat = shufflevector <2 x i32> %b, <2 x i32> undef, <8 x i32> zeroinitializer + %interleaved.vec = shufflevector <8 x i32> %splat, <8 x i32> undef, <8 x i32> + store <8 x i32> %interleaved.vec, <8 x i32>* %a, align 4 + ret void +} + ; NOTE: Currently all CONCAT_VECTORS get expanded so there's little point in ; validating all combinations of vector type.