Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -88,7 +88,7 @@ return nullptr; } -// Constant fold bitcast, symbolically evaluating it with DataLayout. +/// Constant fold bitcast, symbolically evaluating it with DataLayout. /// This always returns a non-null constant, but it may be a /// ConstantExpr if unfoldable. Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) { @@ -99,31 +99,33 @@ !DestTy->isPtrOrPtrVectorTy()) // Don't get ones for ptr types! return Constant::getAllOnesValue(DestTy); - // Handle a vector->integer cast. - if (auto *IT = dyn_cast(DestTy)) { - auto *VTy = dyn_cast(C->getType()); - if (!VTy) - return ConstantExpr::getBitCast(C, DestTy); + if (auto *VTy = dyn_cast(C->getType())) { + // Handle a vector->integer cast. + if (isa(DestTy) || DestTy->isFloatingPointTy()) { + unsigned NumSrcElts = VTy->getNumElements(); + Type *SrcEltTy = VTy->getElementType(); + + // If the vector is a vector of floating point, convert it to vector of int + // to simplify things. + if (SrcEltTy->isFloatingPointTy()) { + unsigned FPWidth = SrcEltTy->getPrimitiveSizeInBits(); + Type *SrcIVTy = + VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumSrcElts); + // Ask IR to do the conversion now that #elts line up. + C = ConstantExpr::getBitCast(C, SrcIVTy); + } - unsigned NumSrcElts = VTy->getNumElements(); - Type *SrcEltTy = VTy->getElementType(); - - // If the vector is a vector of floating point, convert it to vector of int - // to simplify things. - if (SrcEltTy->isFloatingPointTy()) { - unsigned FPWidth = SrcEltTy->getPrimitiveSizeInBits(); - Type *SrcIVTy = - VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumSrcElts); - // Ask IR to do the conversion now that #elts line up. - C = ConstantExpr::getBitCast(C, SrcIVTy); - } + APInt Result(DL.getTypeSizeInBits(DestTy), 0); + if (Constant *CE = foldConstVectorToAPInt(Result, DestTy, C, + SrcEltTy, NumSrcElts, DL)) + return CE; - APInt Result(IT->getBitWidth(), 0); - if (Constant *CE = foldConstVectorToAPInt(Result, DestTy, C, - SrcEltTy, NumSrcElts, DL)) - return CE; + if (isa(DestTy)) + return ConstantInt::get(DestTy, Result); - return ConstantInt::get(IT, Result); + APFloat FP(DestTy->getFltSemantics(), Result); + return ConstantFP::get(DestTy->getContext(), FP); + } } // The code below only handles casts to vectors currently. Index: test/Transforms/InstCombine/bitcast.ll =================================================================== --- test/Transforms/InstCombine/bitcast.ll +++ test/Transforms/InstCombine/bitcast.ll @@ -427,3 +427,67 @@ %res = bitcast <8 x i1> to i8 ret i8 %res } + +@g = internal unnamed_addr global i32 undef + +; CHECK-LABEL: @constant_fold_vector_to_double( +; CHECK: store volatile double 1.000000e+00, +; CHECK: store volatile double 1.000000e+00, +; CHECK: store volatile double 1.000000e+00, +; CHECK: store volatile double 1.000000e+00, + +; CHECK: store volatile double 0xFFFFFFFFFFFFFFFF, +; CHECK: store volatile double 0x162E000004D2, + +; CHECK: store volatile double bitcast (<2 x i32> to double), +; CHECK: store volatile double 0x400000003F800000, + +; CHECK: store volatile double 0.000000e+00, +; CHECK: store volatile double 0.000000e+00, +; CHECK: store volatile double 0.000000e+00, +; CHECK: store volatile double 0.000000e+00, +; CHECK: store volatile double 0.000000e+00, +; CHECK: store volatile double 0.000000e+00, +define void @constant_fold_vector_to_double() { + store volatile double bitcast (<1 x i64> to double), double* undef + store volatile double bitcast (<2 x i32> to double), double* undef + store volatile double bitcast (<4 x i16> to double), double* undef + store volatile double bitcast (<8 x i8> to double), double* undef + + store volatile double bitcast (<2 x i32> to double), double* undef + store volatile double bitcast (<2 x i32> to double), double* undef + + store volatile double bitcast (<2 x i32> to double), double* undef + store volatile double bitcast (<2 x float> to double), double* undef + + store volatile double bitcast (<2 x i32> zeroinitializer to double), double* undef + store volatile double bitcast (<4 x i16> zeroinitializer to double), double* undef + store volatile double bitcast (<8 x i8> zeroinitializer to double), double* undef + store volatile double bitcast (<16 x i4> zeroinitializer to double), double* undef + store volatile double bitcast (<32 x i2> zeroinitializer to double), double* undef + store volatile double bitcast (<64 x i1> zeroinitializer to double), double* undef + ret void +} + +; CHECK-LABEL: @constant_fold_vector_to_float( +; CHECK: store volatile float 1.000000e+00, +; CHECK: store volatile float 1.000000e+00, +; CHECK: store volatile float 1.000000e+00, +; CHECK: store volatile float 1.000000e+00, +define void @constant_fold_vector_to_float() { + store volatile float bitcast (<1 x i32> to float), float* undef + store volatile float bitcast (<2 x i16> to float), float* undef + store volatile float bitcast (<4 x i8> to float), float* undef + store volatile float bitcast (<32 x i1> to float), float* undef + + ret void +} + +; CHECK-LABEL: @constant_fold_vector_to_half( +; CHECK: store volatile half 0xH4000, +; CHECK: store volatile half 0xH4000, +define void @constant_fold_vector_to_half() { + store volatile half bitcast (<2 x i8> to half), half* undef + store volatile half bitcast (<4 x i4> to half), half* undef + ret void +}