Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2858,23 +2858,43 @@ // FIXME: Entirely reasonable to perform folding of other unary // operations here as the need arises. break; - case ISD::TRUNCATE: - // Constant build vector truncation can be done with the original scalar - // operands but with a new build vector with the truncated value type. - return getNode(ISD::BUILD_VECTOR, DL, VT, BV->ops()); case ISD::FNEG: case ISD::FABS: case ISD::FCEIL: case ISD::FTRUNC: case ISD::FFLOOR: case ISD::FP_EXTEND: + case ISD::TRUNCATE: case ISD::UINT_TO_FP: case ISD::SINT_TO_FP: { + EVT SVT = VT.getScalarType(); + EVT InVT = BV->getValueType(0); + EVT InSVT = InVT.getScalarType(); + + // Find legal integer scalar type for constant promotion. + EVT LegalSVT = SVT; + if (SVT.isInteger()) { + LegalSVT = TLI->getTypeToTransformTo(*getContext(), SVT); + assert(LegalSVT.bitsGE(SVT) && "Unexpected legal scalar type size"); + } + // Let the above scalar folding handle the folding of each element. SmallVector Ops; for (int i = 0, e = VT.getVectorNumElements(); i != e; ++i) { SDValue OpN = BV->getOperand(i); - OpN = getNode(Opcode, DL, VT.getVectorElementType(), OpN); + EVT OpVT = OpN.getValueType(); + + // Build vector (integer) scalar operands may need implicit + // truncation - do this before constant folding. + if (OpVT.isInteger() && OpVT.bitsGT(InSVT)) + OpN = getNode(ISD::TRUNCATE, DL, InSVT, OpN); + + OpN = getNode(Opcode, DL, SVT, OpN); + + // Legalize the (integer) scalar constant if necessary. + if (LegalSVT != SVT) + OpN = getNode(ISD::ANY_EXTEND, DL, LegalSVT, OpN); + if (OpN.getOpcode() != ISD::UNDEF && OpN.getOpcode() != ISD::Constant && OpN.getOpcode() != ISD::ConstantFP) Index: llvm/trunk/test/CodeGen/X86/fold-vector-bv-crash.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/fold-vector-bv-crash.ll +++ llvm/trunk/test/CodeGen/X86/fold-vector-bv-crash.ll @@ -0,0 +1,17 @@ +; RUN: llc < %s -mtriple=i686-unknown -mattr=+avx +; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx + +; +; llvm-stress generated crash case due to build_vector implicit +; truncation bug from constant folding after legalization. +; + +@G = external global i32 + +define void @bv_crash_test() { + %I = insertelement <4 x i64> zeroinitializer, i64 15910, i32 0 + %Tr = trunc <4 x i64> %I to <4 x i8> + %Bc = bitcast <4 x i8> %Tr to i32 + store volatile i32 %Bc, i32* @G + ret void +} Index: llvm/trunk/test/CodeGen/X86/fold-vector-trunc-sitofp.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/fold-vector-trunc-sitofp.ll +++ llvm/trunk/test/CodeGen/X86/fold-vector-trunc-sitofp.ll @@ -0,0 +1,13 @@ +; RUN: llc < %s -mtriple=i686-unknown -mattr=+avx | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx | FileCheck %s + +; Check that constant integers are correctly being truncated before float conversion + +define <4 x float> @test1() { +; CHECK-LABEL: test1 +; CHECK: movaps {{.*#+}} xmm0 = [-1.000000e+00,0.000000e+00,-1.000000e+00,0.000000e+00] +; CHECK-NEXT: ret + %1 = trunc <4 x i3> to <4 x i1> + %2 = sitofp <4 x i1> %1 to <4 x float> + ret <4 x float> %2 +}