diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -11023,7 +11023,9 @@ // Attempt to pre-truncate BUILD_VECTOR sources. if (N0.getOpcode() == ISD::BUILD_VECTOR && !LegalOperations && - TLI.isTruncateFree(SrcVT.getScalarType(), VT.getScalarType())) { + TLI.isTruncateFree(SrcVT.getScalarType(), VT.getScalarType()) && + // Avoid creating illegal types if running after type legalizer. + (!LegalTypes || TLI.isTypeLegal(VT.getScalarType()))) { SDLoc DL(N); EVT SVT = VT.getScalarType(); SmallVector TruncOps; diff --git a/llvm/test/CodeGen/AArch64/dag-combine-trunc-build-vec.ll b/llvm/test/CodeGen/AArch64/dag-combine-trunc-build-vec.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/dag-combine-trunc-build-vec.ll @@ -0,0 +1,48 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64 < %s | FileCheck %s + +; This test is reduced fom https://github.com/android/ndk/issues/1207 for an +; issue with the following DAGCobmine operation: +; truncate(build_vector(x,y)) -> build_vector(truncate(x),truncate(y)) +; The combine should avoid creating illegal types if types have already been +; legalized. + +define void @no_combine(i32 %p) local_unnamed_addr { +; CHECK-LABEL: no_combine: +; CHECK: // %bb.0: +; CHECK-NEXT: dup v0.4s, w0 +; CHECK-NEXT: movi v1.4h, #4 +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: mov v0.d[1], v1.d[0] +; CHECK-NEXT: xtn v1.8b, v0.8h +; CHECK-NEXT: xtn2 v1.16b, v0.8h +; CHECK-NEXT: str q1, [x8] +; CHECK-NEXT: ret + +; The two shufflevector operations are needed to force the DAGCombine to happen +; after type legalization and before operation legalization. Removing either +; makes the combine to happen before type legalization and the issue no longer +; repros. + %1 = insertelement <16 x i32> undef, i32 %p, i32 0 + %2 = shufflevector <16 x i32> %1, <16 x i32> undef, <16 x i32> + %3 = shufflevector <16 x i32> %2, <16 x i32> , <16 x i32> + %4 = trunc <16 x i32> %3 to <16 x i8> + %5 = bitcast i8* undef to <16 x i8>* + store <16 x i8> %4, <16 x i8>* %5, align 1 + ret void +} + +; Test case to ensure that the combine is done before type legalization. +define void @do_combine(i32 %p) local_unnamed_addr { +; CHECK-LABEL: do_combine: +; CHECK: // %bb.0: +; CHECK-NEXT: dup v0.16b, w0 +; CHECK-NEXT: str q0, [x8] +; CHECK-NEXT: ret + %1 = insertelement <16 x i32> undef, i32 %p, i32 0 + %2 = shufflevector <16 x i32> %1, <16 x i32> undef, <16 x i32> + %3 = trunc <16 x i32> %2 to <16 x i8> + %4 = bitcast i8* undef to <16 x i8>* + store <16 x i8> %3, <16 x i8>* %4, align 1 + ret void +}