Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -1236,6 +1236,7 @@ case Intrinsic::sqrt: case Intrinsic::sin: case Intrinsic::cos: + case Intrinsic::trunc: case Intrinsic::pow: case Intrinsic::powi: case Intrinsic::bswap: @@ -1422,6 +1423,24 @@ 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); + } + /// 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 +1467,6 @@ 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: Index: test/Transforms/InstCombine/intrinsics.ll =================================================================== --- test/Transforms/InstCombine/intrinsics.ll +++ test/Transforms/InstCombine/intrinsics.ll @@ -19,6 +19,9 @@ 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 define i8 @uaddtest1(i8 %A, i8 %B) { %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 %B) @@ -447,3 +450,39 @@ ; 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 +}