[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
This commit is contained in:
Bixia Zheng 2019-03-22 16:37:37 +00:00
parent 71ebc9eb0b
commit bdf0230cff
2 changed files with 12 additions and 4 deletions

View File

@ -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");

View File

@ -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