From: Sanjay Patel Date: Fri, 10 Oct 2014 23:00:21 +0000 (+0000) Subject: Return undef on FP <-> Int conversions that overflow (PR21330). X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=add74ff5fff48ef66b1b6133f2093079cdb42af1;p=oota-llvm.git Return undef on FP <-> Int conversions that overflow (PR21330). The LLVM Lang Ref states for signed/unsigned int to float conversions: "If the value cannot fit in the floating point value, the results are undefined." And for FP to signed/unsigned int: "If the value cannot fit in ty2, the results are undefined." This matches the C definitions. The existing behavior pins to infinity or a max int value, but that may just lead to more confusion as seen in: http://llvm.org/bugs/show_bug.cgi?id=21130 Returning undef will hopefully lead to a less silent failure. Differential Revision: http://reviews.llvm.org/D5603 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219542 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index b96d1540d71..cdfb41f7dcc 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -593,8 +593,13 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, bool ignored; uint64_t x[2]; uint32_t DestBitWidth = cast(DestTy)->getBitWidth(); - (void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI, - APFloat::rmTowardZero, &ignored); + if (APFloat::opInvalidOp == + V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI, + APFloat::rmTowardZero, &ignored)) { + // Undefined behavior invoked - the destination type can't represent + // the input constant. + return UndefValue::get(DestTy); + } APInt Val(DestBitWidth, x); return ConstantInt::get(FPC->getContext(), Val); } @@ -653,9 +658,13 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, APInt api = CI->getValue(); APFloat apf(DestTy->getFltSemantics(), APInt::getNullValue(DestTy->getPrimitiveSizeInBits())); - (void)apf.convertFromAPInt(api, - opc==Instruction::SIToFP, - APFloat::rmNearestTiesToEven); + if (APFloat::opOverflow & + apf.convertFromAPInt(api, opc==Instruction::SIToFP, + APFloat::rmNearestTiesToEven)) { + // Undefined behavior invoked - the destination type can't represent + // the input constant. + return UndefValue::get(DestTy); + } return ConstantFP::get(V->getContext(), apf); } return nullptr; diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index 47f7e73f998..891fcaa68fd 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -1050,3 +1050,37 @@ define i8 @test85(i32 %a) { ; CHECK: [[SHR:%.*]] = lshr exact i32 [[ADD]], 23 ; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8 } + +; Overflow on a float to int or int to float conversion is undefined (PR21130). + +define i8 @overflow_fptosi() { + %i = fptosi double 1.56e+02 to i8 + ret i8 %i +; CHECK-LABEL: @overflow_fptosi( +; CHECK-NEXT: ret i8 undef +} + +define i8 @overflow_fptoui() { + %i = fptoui double 2.56e+02 to i8 + ret i8 %i +; CHECK-LABEL: @overflow_fptoui( +; CHECK-NEXT: ret i8 undef +} + +; The maximum float is approximately 2 ** 128 which is 3.4E38. +; The constant below is 4E38. Use a 130 bit integer to hold that +; number; 129-bits for the value + 1 bit for the sign. +define float @overflow_uitofp() { + %i = uitofp i130 400000000000000000000000000000000000000 to float + ret float %i +; CHECK-LABEL: @overflow_uitofp( +; CHECK-NEXT: ret float undef +} + +define float @overflow_sitofp() { + %i = sitofp i130 400000000000000000000000000000000000000 to float + ret float %i +; CHECK-LABEL: @overflow_sitofp( +; CHECK-NEXT: ret float undef +} +