mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[SimplifyLibCalls] Improve double->float shrinking to consider constants
This allows cases like float x; fmin(1.0, x); to be optimized to fminf(1.0f, x); rdar://19049359 Differential Revision: http://reviews.llvm.org/D6496 llvm-svn: 223270
This commit is contained in:
parent
3bca19851f
commit
8672c85e5e
@ -1031,6 +1031,28 @@ Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) {
|
||||
// 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<FPExtInst>(Val)) {
|
||||
Value *Op = Cast->getOperand(0);
|
||||
if (Op->getType()->isFloatTy())
|
||||
return Op;
|
||||
}
|
||||
if (ConstantFP *Const = dyn_cast<ConstantFP>(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 @@ Value *LibCallSimplifier::optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B,
|
||||
}
|
||||
|
||||
// If this is something like 'floor((double)floatval)', convert to floorf.
|
||||
FPExtInst *Cast = dyn_cast<FPExtInst>(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 @@ Value *LibCallSimplifier::optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B) {
|
||||
return nullptr;
|
||||
|
||||
// If this is something like 'fmin((double)floatval1, (double)floatval2)',
|
||||
// we convert it to fminf.
|
||||
FPExtInst *Cast1 = dyn_cast<FPExtInst>(CI->getArgOperand(0));
|
||||
FPExtInst *Cast2 = dyn_cast<FPExtInst>(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());
|
||||
}
|
||||
|
||||
|
@ -235,6 +235,30 @@ define i32 @test19(float %x, float %y, float %z) nounwind uwtable {
|
||||
; 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
|
||||
|
Loading…
Reference in New Issue
Block a user