Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -58,6 +58,38 @@ // Constant Folding internal helper functions //===----------------------------------------------------------------------===// +static Constant *foldConstVectorToAPInt(APInt &Result, + Type *DestTy, + Constant *C, + Type *SrcEltTy, + unsigned NumSrcElts, + const DataLayout &DL) { + // Now that we know that the input value is a vector of integers, just shift + // and insert them into our result. + unsigned BitShift = DL.getTypeSizeInBits(SrcEltTy); + for (unsigned i = 0; i != NumSrcElts; ++i) { + Constant *Element; + if (DL.isLittleEndian()) + Element = C->getAggregateElement(NumSrcElts - i - 1); + else + Element = C->getAggregateElement(i); + + if (Element && isa(Element)) { + Result <<= BitShift; + continue; + } + + auto *ElementCI = dyn_cast_or_null(Element); + if (!ElementCI) + return ConstantExpr::getBitCast(C, DestTy); + + Result <<= BitShift; + Result |= ElementCI->getValue().zextOrSelf(Result.getBitWidth()); + } + + return nullptr; +} + /// Constant fold bitcast, symbolically evaluating it with DataLayout. /// This always returns a non-null constant, but it may be a /// ConstantExpr if unfoldable. @@ -69,50 +101,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); - - 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); - } - - // Now that we know that the input value is a vector of integers, just shift - // and insert them into our result. - unsigned BitShift = DL.getTypeSizeInBits(SrcEltTy); - APInt Result(IT->getBitWidth(), 0); - for (unsigned i = 0; i != NumSrcElts; ++i) { - Constant *Element; - if (DL.isLittleEndian()) - Element = C->getAggregateElement(NumSrcElts-i-1); - else - Element = C->getAggregateElement(i); - - if (Element && isa(Element)) { - Result <<= BitShift; - continue; + 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); } - auto *ElementCI = dyn_cast_or_null(Element); - if (!ElementCI) - return ConstantExpr::getBitCast(C, DestTy); + APInt Result(DL.getTypeSizeInBits(DestTy), 0); + if (Constant *CE = foldConstVectorToAPInt(Result, DestTy, C, + SrcEltTy, NumSrcElts, DL)) + return CE; - Result <<= BitShift; - Result |= ElementCI->getValue().zextOrSelf(IT->getBitWidth()); - } + 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 @@ -406,3 +406,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 +}