From 8ce6c7b366da47c0f15dd4654e1364b1da76f4cf Mon Sep 17 00:00:00 2001 From: Bixia Zheng Date: Fri, 22 Mar 2019 16:37:37 +0000 Subject: [PATCH] [ConstantFolding] Fix GetConstantFoldFPValue to avoid cast overflow. Summary: In C++, the behavior of casting a double value that is beyond the range of a single precision floating-point to a float value is undefined. This change replaces such a cast with APFloat::convert to convert the value, which is consistent with how we convert a double value to a half value. Reviewers: sanjoy Subscribers: lebedev.ri, sanjoy, jlebar, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59500 llvm-svn: 356781 --- lib/Analysis/ConstantFolding.cpp | 6 ++---- test/Transforms/ConstProp/calls.ll | 10 ++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 3b4e6031566..74468e8dd72 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -1517,14 +1517,12 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { namespace { Constant *GetConstantFoldFPValue(double V, Type *Ty) { - if (Ty->isHalfTy()) { + if (Ty->isHalfTy() || Ty->isFloatTy()) { APFloat APF(V); bool unused; - APF.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &unused); + APF.convert(Ty->getFltSemantics(), APFloat::rmNearestTiesToEven, &unused); return ConstantFP::get(Ty->getContext(), APF); } - if (Ty->isFloatTy()) - return ConstantFP::get(Ty->getContext(), APFloat((float)V)); if (Ty->isDoubleTy()) return ConstantFP::get(Ty->getContext(), APFloat(V)); llvm_unreachable("Can only constant fold half/float/double"); diff --git a/test/Transforms/ConstProp/calls.ll b/test/Transforms/ConstProp/calls.ll index 161637cc92b..12ee1cb1139 100644 --- a/test/Transforms/ConstProp/calls.ll +++ b/test/Transforms/ConstProp/calls.ll @@ -193,4 +193,14 @@ entry: ret double %0 } +define float @test_intrinsic_pow_f32_overflow() nounwind uwtable ssp { +entry: +; CHECK-LABEL: @test_intrinsic_pow_f32_overflow( +; CHECK-NOT: call +; CHECK: ret float 0x7FF0000000000000 + %0 = call float @llvm.pow.f32(float 40.0, float 50.0) + ret float %0 +} + declare double @llvm.pow.f64(double, double) nounwind readonly +declare float @llvm.pow.f32(float, float) nounwind readonly