From d818e38ff979c21577abada60057c83946852aeb Mon Sep 17 00:00:00 2001 From: Karthik Bhat Date: Tue, 21 Jul 2015 08:52:23 +0000 Subject: [PATCH] Constfold trunc,rint,nearbyint,ceil and floor using APFloat A patch by Chakshu Grover! This patch allows constfolding of trunc,rint,nearbyint,ceil and floor intrinsics using APFloat class. Differential Revision: http://reviews.llvm.org/D11144 llvm-svn: 242763 --- llvm/lib/Analysis/ConstantFolding.cpp | 37 +++++++++-- .../test/Transforms/InstCombine/intrinsics.ll | 65 +++++++++++++++++++ 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 02a5aef03223..bd9439ec4d63 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1236,6 +1236,9 @@ bool llvm::canConstantFoldCallTo(const Function *F) { case Intrinsic::sqrt: case Intrinsic::sin: case Intrinsic::cos: + case Intrinsic::trunc: + case Intrinsic::rint: + case Intrinsic::nearbyint: case Intrinsic::pow: case Intrinsic::powi: case Intrinsic::bswap: @@ -1422,6 +1425,36 @@ static Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, return ConstantFP::get(Ty->getContext(), V); } + if (IntrinsicID == Intrinsic::floor) { + APFloat V = Op->getValueAPF(); + V.roundToIntegral(APFloat::rmTowardNegative); + return ConstantFP::get(Ty->getContext(), V); + } + + if (IntrinsicID == Intrinsic::ceil) { + APFloat V = Op->getValueAPF(); + V.roundToIntegral(APFloat::rmTowardPositive); + return ConstantFP::get(Ty->getContext(), V); + } + + if (IntrinsicID == Intrinsic::trunc) { + APFloat V = Op->getValueAPF(); + V.roundToIntegral(APFloat::rmTowardZero); + return ConstantFP::get(Ty->getContext(), V); + } + + if (IntrinsicID == Intrinsic::rint) { + APFloat V = Op->getValueAPF(); + V.roundToIntegral(APFloat::rmNearestTiesToEven); + return ConstantFP::get(Ty->getContext(), V); + } + + if (IntrinsicID == Intrinsic::nearbyint) { + APFloat V = Op->getValueAPF(); + V.roundToIntegral(APFloat::rmNearestTiesToEven); + return ConstantFP::get(Ty->getContext(), V); + } + /// We only fold functions with finite arguments. Folding NaN and inf is /// likely to be aborted with an exception anyway, and some host libms /// have known errors raising exceptions. @@ -1448,10 +1481,6 @@ static Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, return ConstantFoldFP(exp, V, Ty); case Intrinsic::exp2: return ConstantFoldFP(exp2, V, Ty); - case Intrinsic::floor: - return ConstantFoldFP(floor, V, Ty); - case Intrinsic::ceil: - return ConstantFoldFP(ceil, V, Ty); case Intrinsic::sin: return ConstantFoldFP(sin, V, Ty); case Intrinsic::cos: diff --git a/llvm/test/Transforms/InstCombine/intrinsics.ll b/llvm/test/Transforms/InstCombine/intrinsics.ll index bea063787a75..88f032498271 100644 --- a/llvm/test/Transforms/InstCombine/intrinsics.ll +++ b/llvm/test/Transforms/InstCombine/intrinsics.ll @@ -19,6 +19,11 @@ declare i32 @llvm.ctpop.i32(i32) nounwind readnone declare i8 @llvm.ctlz.i8(i8, i1) nounwind readnone declare double @llvm.cos.f64(double %Val) nounwind readonly declare double @llvm.sin.f64(double %Val) nounwind readonly +declare double @llvm.floor.f64(double %Val) nounwind readonly +declare double @llvm.ceil.f64(double %Val) nounwind readonly +declare double @llvm.trunc.f64(double %Val) nounwind readonly +declare double @llvm.rint.f64(double %Val) nounwind readonly +declare double @llvm.nearbyint.f64(double %Val) nounwind readonly define i8 @uaddtest1(i8 %A, i8 %B) { %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 %B) @@ -447,3 +452,63 @@ entry: ; CHECK-LABEL: @sin( ; CHECK: store volatile double 0.000000e+00, double* %P } + +define void @floor(double *%P) { +entry: + %B = tail call double @llvm.floor.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.floor.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @floor( +; CHECK: store volatile double 1.000000e+00, double* %P, align 8 +; CHECK: store volatile double -2.000000e+00, double* %P, align 8 +} + +define void @ceil(double *%P) { +entry: + %B = tail call double @llvm.ceil.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.ceil.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @ceil( +; CHECK: store volatile double 2.000000e+00, double* %P, align 8 +; CHECK: store volatile double -1.000000e+00, double* %P, align 8 +} + +define void @trunc(double *%P) { +entry: + %B = tail call double @llvm.trunc.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.trunc.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @trunc( +; CHECK: store volatile double 1.000000e+00, double* %P, align 8 +; CHECK: store volatile double -1.000000e+00, double* %P, align 8 +} + +define void @rint(double *%P) { +entry: + %B = tail call double @llvm.rint.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.rint.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @rint( +; CHECK: store volatile double 2.000000e+00, double* %P, align 8 +; CHECK: store volatile double -2.000000e+00, double* %P, align 8 +} + +define void @nearbyint(double *%P) { +entry: + %B = tail call double @llvm.nearbyint.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.nearbyint.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @nearbyint( +; CHECK: store volatile double 2.000000e+00, double* %P, align 8 +; CHECK: store volatile double -2.000000e+00, double* %P, align 8 +}