Index: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1031,6 +1031,28 @@ // Math Library Optimizations //===----------------------------------------------------------------------===// +/// Return a variant of Val with float type. +/// Currently this works in two cases: If Val is an FPExtension of a float +/// value to something bigger, simply return the operand. +/// If Val is a ConstantFP but can be converted to a float ConstantFP without +/// loss of precision do so. +static Value *valueHasFloatPrecision(Value *Val) { + if (FPExtInst *Cast = dyn_cast(Val)) { + Value *Op = Cast->getOperand(0); + if (Op->getType()->isFloatTy()) + return Op; + } + if (ConstantFP *Const = dyn_cast(Val)) { + APFloat F = Const->getValueAPF(); + bool loosesInfo; + (void)F.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, + &loosesInfo); + if (!loosesInfo) + return ConstantFP::get(Const->getContext(), F); + } + return nullptr; +} + //===----------------------------------------------------------------------===// // Double -> Float Shrinking Optimizations for Unary Functions like 'floor' @@ -1052,12 +1074,11 @@ } // If this is something like 'floor((double)floatval)', convert to floorf. - FPExtInst *Cast = dyn_cast(CI->getArgOperand(0)); - if (!Cast || !Cast->getOperand(0)->getType()->isFloatTy()) + Value *V = valueHasFloatPrecision(CI->getArgOperand(0)); + if (V == nullptr) return nullptr; // floor((double)floatval) -> (double)floorf(floatval) - Value *V = Cast->getOperand(0); if (Callee->isIntrinsic()) { Module *M = CI->getParent()->getParent()->getParent(); Intrinsic::ID IID = (Intrinsic::ID) Callee->getIntrinsicID(); @@ -1083,21 +1104,19 @@ return nullptr; // If this is something like 'fmin((double)floatval1, (double)floatval2)', - // we convert it to fminf. - FPExtInst *Cast1 = dyn_cast(CI->getArgOperand(0)); - FPExtInst *Cast2 = dyn_cast(CI->getArgOperand(1)); - if (!Cast1 || !Cast1->getOperand(0)->getType()->isFloatTy() || !Cast2 || - !Cast2->getOperand(0)->getType()->isFloatTy()) + // or fmin(1.0, (double)floatval), then we convert it to fminf. + Value *V1 = valueHasFloatPrecision(CI->getArgOperand(0)); + if (V1 == nullptr) + return nullptr; + Value *V2 = valueHasFloatPrecision(CI->getArgOperand(1)); + if (V2 == nullptr) return nullptr; // fmin((double)floatval1, (double)floatval2) - // -> (double)fmin(floatval1, floatval2) - Value *V = nullptr; - Value *V1 = Cast1->getOperand(0); - Value *V2 = Cast2->getOperand(0); + // -> (double)fminf(floatval1, floatval2) // TODO: Handle intrinsics in the same way as in optimizeUnaryDoubleFP(). - V = EmitBinaryFloatFnCall(V1, V2, Callee->getName(), B, - Callee->getAttributes()); + Value *V = EmitBinaryFloatFnCall(V1, V2, Callee->getName(), B, + Callee->getAttributes()); return B.CreateFPExt(V, B.getDoubleTy()); } Index: llvm/trunk/test/Transforms/InstCombine/float-shrink-compare.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/float-shrink-compare.ll +++ llvm/trunk/test/Transforms/InstCombine/float-shrink-compare.ll @@ -235,6 +235,30 @@ ; CHECK-NEXT: fcmp oeq float %copysignf, %z } +define i32 @test20(float %x, float %y) nounwind uwtable { + %1 = fpext float %y to double + %2 = fpext float %x to double + %3 = call double @fmin(double 1.000000e+00, double %2) nounwind + %4 = fcmp oeq double %1, %3 + %5 = zext i1 %4 to i32 + ret i32 %5 +; CHECK-LABEL: @test20( +; CHECK-NEXT: %fminf = call float @fminf(float 1.000000e+00, float %x) +; CHECK-NEXT: fcmp oeq float %fminf, %y +} + +define i32 @test21(float %x, float %y) nounwind uwtable { + %1 = fpext float %y to double + %2 = fpext float %x to double + %3 = call double @fmin(double 1.300000e+00, double %2) nounwind + %4 = fcmp oeq double %1, %3 + %5 = zext i1 %4 to i32 + ret i32 %5 +; should not be changed to fminf as the constant would loose precision +; CHECK-LABEL: @test21( +; CHECK: %3 = call double @fmin(double 1.300000e+00, double %2) +} + declare double @fabs(double) nounwind readnone declare double @ceil(double) nounwind readnone declare double @copysign(double, double) nounwind readnone