[llvm] [InstCombine] Convert @log to @llvm.log if the input is known positive. (PR #111428)

David Green via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 7 12:56:33 PDT 2024


https://github.com/davemgreen created https://github.com/llvm/llvm-project/pull/111428

Similar to 112aac4e8961b9626bb84f36deeaa5a674f03f5a, this converts log libcalls to llvm.log.f64 intrinsics if we know they do not set errno, as the input is not zero and not negative. As log will produce errno if the input is 0 (returning -inf) or if the input is negative (returning nan), we also perform the conversion when we have noinf and nonan.

>From 493cea5ccc5cf796fcabac09736263fd4f496266 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Mon, 7 Oct 2024 20:52:52 +0100
Subject: [PATCH] [InstCombine] Convert @log to @llvm.log if the input is known
 positive.

Similar to 112aac4e8961b9626bb84f36deeaa5a674f03f5a, this converts log libcalls
to llvm.log.f64 intrinsics if we know they do not set errno, as the input is
not zero and not negative. As log will produce errno if the input is 0
(returning -inf) or if the input is negative (returning nan), we also perform
the conversion when we have noinf and nonan.
---
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp |  49 +--
 .../InstCombine/double-float-shrink-1.ll      |  21 +-
 llvm/test/Transforms/InstCombine/log-pow.ll   |   6 +-
 .../InstCombine/log-to-intrinsic.ll           | 279 ++++++++++++++++++
 4 files changed, 325 insertions(+), 30 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/log-to-intrinsic.ll

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 6799d333fb2844..0c1ddc19d7f245 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2510,20 +2510,15 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
   Intrinsic::ID LogID = LogFn->getIntrinsicID();
   Module *Mod = Log->getModule();
   Type *Ty = Log->getType();
-  Value *Ret = nullptr;
 
   if (UnsafeFPShrink && hasFloatVersion(Mod, LogNm))
-    Ret = optimizeUnaryDoubleFP(Log, B, TLI, true);
-
-  // The earlier call must also be 'fast' in order to do these transforms.
-  CallInst *Arg = dyn_cast<CallInst>(Log->getArgOperand(0));
-  if (!Log->isFast() || !Arg || !Arg->isFast() || !Arg->hasOneUse())
-    return Ret;
+    if (Value *Ret = optimizeUnaryDoubleFP(Log, B, TLI, true))
+      return Ret;
 
   LibFunc LogLb, ExpLb, Exp2Lb, Exp10Lb, PowLb;
 
   // This is only applicable to log(), log2(), log10().
-  if (TLI->getLibFunc(LogNm, LogLb))
+  if (TLI->getLibFunc(LogNm, LogLb)) {
     switch (LogLb) {
     case LibFunc_logf:
       LogID = Intrinsic::log;
@@ -2589,10 +2584,26 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
       PowLb = LibFunc_powl;
       break;
     default:
-      return Ret;
+      return nullptr;
+    }
+
+    // Convert libcall to intrinsic if the value is known > 0.
+    bool IsKnownNoErrno = Log->hasNoNaNs() && Log->hasNoInfs();
+    if (!IsKnownNoErrno) {
+      SimplifyQuery SQ(DL, TLI, DT, AC, Log, true, true, DC);
+      KnownFPClass Known = computeKnownFPClass(
+          Log->getOperand(0), KnownFPClass::OrderedLessThanZeroMask,
+          /*Depth=*/0, SQ);
+      IsKnownNoErrno =
+          Known.isKnownNeverZero() && Known.cannotBeOrderedLessThanZero();
+    }
+    if (IsKnownNoErrno) {
+      IRBuilderBase::FastMathFlagGuard Guard(B);
+      B.setFastMathFlags(Log->getFastMathFlags());
+      return B.CreateIntrinsic(LogID, {Ty}, {Log->getArgOperand(0)});
     }
-  else if (LogID == Intrinsic::log || LogID == Intrinsic::log2 ||
-           LogID == Intrinsic::log10) {
+  } else if (LogID == Intrinsic::log || LogID == Intrinsic::log2 ||
+             LogID == Intrinsic::log10) {
     if (Ty->getScalarType()->isFloatTy()) {
       ExpLb = LibFunc_expf;
       Exp2Lb = LibFunc_exp2f;
@@ -2604,9 +2615,14 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
       Exp10Lb = LibFunc_exp10;
       PowLb = LibFunc_pow;
     } else
-      return Ret;
+      return nullptr;
   } else
-    return Ret;
+    return nullptr;
+
+  // The earlier call must also be 'fast' in order to do these transforms.
+  CallInst *Arg = dyn_cast<CallInst>(Log->getArgOperand(0));
+  if (!Log->isFast() || !Arg || !Arg->isFast() || !Arg->hasOneUse())
+    return nullptr;
 
   IRBuilderBase::FastMathFlagGuard Guard(B);
   B.setFastMathFlags(FastMathFlags::getFast());
@@ -2655,7 +2671,7 @@ Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
     return MulY;
   }
 
-  return Ret;
+  return nullptr;
 }
 
 // sqrt(exp(X)) -> exp(X * 0.5)
@@ -2797,13 +2813,13 @@ Value *LibCallSimplifier::optimizeSqrt(CallInst *CI, IRBuilderBase &B) {
 }
 
 Value *LibCallSimplifier::optimizeFMod(CallInst *CI, IRBuilderBase &B) {
-  SimplifyQuery SQ(DL, TLI, DT, AC, CI, true, true, DC);
 
   // fmod(x,y) can set errno if y == 0 or x == +/-inf, and returns Nan in those
   // case. If we know those do not happen, then we can convert the fmod into
   // frem.
   bool IsNoNan = CI->hasNoNaNs();
   if (!IsNoNan) {
+    SimplifyQuery SQ(DL, TLI, DT, AC, CI, true, true, DC);
     KnownFPClass Known0 = computeKnownFPClass(CI->getOperand(0), fcInf,
                                               /*Depth=*/0, SQ);
     if (Known0.isKnownNeverInfinity()) {
@@ -2811,8 +2827,7 @@ Value *LibCallSimplifier::optimizeFMod(CallInst *CI, IRBuilderBase &B) {
           computeKnownFPClass(CI->getOperand(1), fcZero | fcSubnormal,
                               /*Depth=*/0, SQ);
       Function *F = CI->getParent()->getParent();
-      if (Known1.isKnownNeverLogicalZero(*F, CI->getType()))
-        IsNoNan = true;
+      IsNoNan = Known1.isKnownNeverLogicalZero(*F, CI->getType());
     }
   }
 
diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll
index 85c9a01e5fabab..c13a01bb9d4890 100644
--- a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll
+++ b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll
@@ -249,10 +249,10 @@ define double @exp10_test2(float %f)   {
 
 define float @log_test1(float %f)   {
 ; CHECK-LABEL: @log_test1(
-; LINUX-NEXT:    [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]])
+; LINUX-NEXT:    [[LOGF:%.*]] = call fast float @llvm.log.f32(float [[F:%.*]])
 ; LINUX-NEXT:    ret float [[LOGF]]
-; MS32:          [[LOGF:%.*]] = call fast double @log(double [[F:%.*]])
-; MS64-NEXT:     [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]])
+; MS32:          [[LOGF:%.*]] = call fast double @llvm.log.f64(double [[F:%.*]])
+; MS64-NEXT:     [[LOGF:%.*]] = call fast float @llvm.log.f32(float [[F:%.*]])
 ;
   %conv = fpext float %f to double
   %call = call fast double @log(double %conv)
@@ -263,7 +263,7 @@ define float @log_test1(float %f)   {
 define double @log_test2(float %f)   {
 ; CHECK-LABEL: @log_test2(
 ; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
-; CHECK-NEXT:    [[CALL:%.*]] = call fast double @log(double [[CONV]])
+; CHECK-NEXT:    [[CALL:%.*]] = call fast double @llvm.log.f64(double [[CONV]])
 ; CHECK-NEXT:    ret double [[CALL]]
 ;
   %conv = fpext float %f to double
@@ -273,10 +273,10 @@ define double @log_test2(float %f)   {
 
 define float @log10_test1(float %f)   {
 ; CHECK-LABEL: @log10_test1(
-; LINUX-NEXT:    [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]])
+; LINUX-NEXT:    [[LOG10F:%.*]] = call fast float @llvm.log10.f32(float [[F:%.*]])
 ; LINUX-NEXT:    ret float [[LOG10F]]
-; MS32:          [[LOG10F:%.*]] = call fast double @log10(double [[F:%.*]])
-; MS64-NEXT:     [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]])
+; MS32:          [[LOG10F:%.*]] = call fast double @llvm.log10.f64(double [[F:%.*]])
+; MS64-NEXT:     [[LOG10F:%.*]] = call fast float @llvm.log10.f32(float [[F:%.*]])
 ;
   %conv = fpext float %f to double
   %call = call fast double @log10(double %conv)
@@ -287,7 +287,7 @@ define float @log10_test1(float %f)   {
 define double @log10_test2(float %f) {
 ; CHECK-LABEL: @log10_test2(
 ; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
-; CHECK-NEXT:    [[CALL:%.*]] = call fast double @log10(double [[CONV]])
+; CHECK-NEXT:    [[CALL:%.*]] = call fast double @llvm.log10.f64(double [[CONV]])
 ; CHECK-NEXT:    ret double [[CALL]]
 ;
   %conv = fpext float %f to double
@@ -320,7 +320,7 @@ define double @log1p_test2(float %f)   {
 
 define float @log2_test1(float %f)   {
 ; CHECK-LABEL: @log2_test1(
-; ISC99-NEXT:    [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]])
+; ISC99-NEXT:    [[LOG2F:%.*]] = call fast float @llvm.log2.f32(float [[F:%.*]])
 ; ISC99-NEXT:    ret float [[LOG2F]]
 ; ISC89:         [[LOG2F:%.*]] = call fast double @log2(double [[F:%.*]])
 ;
@@ -333,7 +333,8 @@ define float @log2_test1(float %f)   {
 define double @log2_test2(float %f)   {
 ; CHECK-LABEL: @log2_test2(
 ; CHECK-NEXT:    [[CONV:%.*]] = fpext float [[F:%.*]] to double
-; CHECK-NEXT:    [[CALL:%.*]] = call fast double @log2(double [[CONV]])
+; ISC99-NEXT:    [[CALL:%.*]] = call fast double @llvm.log2.f64(double [[CONV]])
+; ISC89-NEXT:    [[LOG2F:%.*]] = call fast double @log2(double [[F:%.*]])
 ; CHECK-NEXT:    ret double [[CALL]]
 ;
   %conv = fpext float %f to double
diff --git a/llvm/test/Transforms/InstCombine/log-pow.ll b/llvm/test/Transforms/InstCombine/log-pow.ll
index b628e7cc57f15f..bfa636e470bb45 100644
--- a/llvm/test/Transforms/InstCombine/log-pow.ll
+++ b/llvm/test/Transforms/InstCombine/log-pow.ll
@@ -73,7 +73,7 @@ define float @logf_powfi_nonconst(float %x, i32 %y) {
 define double @log_powi_not_fast(double %x, i32 %y) {
 ; CHECK-LABEL: @log_powi_not_fast(
 ; CHECK-NEXT:    [[POW:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]])
-; CHECK-NEXT:    [[LOG:%.*]] = call fast double @log(double [[POW]])
+; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log.f64(double [[POW]])
 ; CHECK-NEXT:    ret double [[LOG]]
 ;
   %pow = call double @llvm.powi.f64.i32(double %x, i32 %y)
@@ -106,7 +106,7 @@ define <2 x double> @log2v_powv(<2 x double> %x, <2 x double> %y) {
 define double @log_pow_not_fast(double %x, double %y) {
 ; CHECK-LABEL: @log_pow_not_fast(
 ; CHECK-NEXT:    [[POW:%.*]] = call double @pow(double [[X:%.*]], double [[Y:%.*]])
-; CHECK-NEXT:    [[LOG:%.*]] = call fast double @log(double [[POW]])
+; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log.f64(double [[POW]])
 ; CHECK-NEXT:    ret double [[LOG]]
 ;
   %pow = call double @pow(double %x, double %y)
@@ -158,7 +158,7 @@ define float @log2f_exp10f(float %x) {
 define double @log_exp2_not_fast(double %x) {
 ; CHECK-LABEL: @log_exp2_not_fast(
 ; CHECK-NEXT:    [[EXP:%.*]] = call double @exp2(double [[X:%.*]])
-; CHECK-NEXT:    [[LOG:%.*]] = call fast double @log(double [[EXP]])
+; CHECK-NEXT:    [[LOG:%.*]] = call fast double @llvm.log.f64(double [[EXP]])
 ; CHECK-NEXT:    ret double [[LOG]]
 ;
   %exp = call double @exp2(double %x)
diff --git a/llvm/test/Transforms/InstCombine/log-to-intrinsic.ll b/llvm/test/Transforms/InstCombine/log-to-intrinsic.ll
new file mode 100644
index 00000000000000..3ee91f4edf50f5
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/log-to-intrinsic.ll
@@ -0,0 +1,279 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+define float @test_logf_pos(float %f) {
+; CHECK-LABEL: define float @test_logf_pos(
+; CHECK-SAME: float [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.log.f32(float [[F]])
+; CHECK-NEXT:    ret float [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+entry:
+  %isinf = fcmp ole float %f, 0x0000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call float @logf(float %f)
+  ret float %call
+
+return:
+  ret float 0.0
+}
+
+define double @test_log_pos(double %f) {
+; CHECK-LABEL: define double @test_log_pos(
+; CHECK-SAME: double [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call double @llvm.log.f64(double [[F]])
+; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret double 0.000000e+00
+;
+entry:
+  %isinf = fcmp ole double %f, 0x0000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call double @log(double %f)
+  ret double %call
+
+return:
+  ret double 0.0
+}
+
+define fp128 @test_logl_pos(fp128 %f) {
+; CHECK-LABEL: define fp128 @test_logl_pos(
+; CHECK-SAME: fp128 [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt fp128 [[F]], 0xL00000000000000000000000000000000
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call fp128 @llvm.log.f128(fp128 [[F]])
+; CHECK-NEXT:    ret fp128 [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret fp128 0xL00000000000000000000000000000000
+;
+entry:
+  %isinf = fcmp ole fp128 %f, 0xL00000000000000000000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call fp128 @logl(fp128 %f)
+  ret fp128 %call
+
+return:
+  ret fp128 0xL00000000000000000000000000000000
+}
+
+define float @test_log10f_pos(float %f) {
+; CHECK-LABEL: define float @test_log10f_pos(
+; CHECK-SAME: float [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.log10.f32(float [[F]])
+; CHECK-NEXT:    ret float [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+entry:
+  %isinf = fcmp ole float %f, 0x0000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call float @log10f(float %f)
+  ret float %call
+
+return:
+  ret float 0.0
+}
+
+define double @test_log10_pos(double %f) {
+; CHECK-LABEL: define double @test_log10_pos(
+; CHECK-SAME: double [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call double @llvm.log10.f64(double [[F]])
+; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret double 0.000000e+00
+;
+entry:
+  %isinf = fcmp ole double %f, 0x0000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call double @log10(double %f)
+  ret double %call
+
+return:
+  ret double 0.0
+}
+
+define fp128 @test_log10l_pos(fp128 %f) {
+; CHECK-LABEL: define fp128 @test_log10l_pos(
+; CHECK-SAME: fp128 [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt fp128 [[F]], 0xL00000000000000000000000000000000
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call fp128 @llvm.log10.f128(fp128 [[F]])
+; CHECK-NEXT:    ret fp128 [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret fp128 0xL00000000000000000000000000000000
+;
+entry:
+  %isinf = fcmp ole fp128 %f, 0xL00000000000000000000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call fp128 @log10l(fp128 %f)
+  ret fp128 %call
+
+return:
+  ret fp128 0xL00000000000000000000000000000000
+}
+
+define float @test_log2f_pos(float %f) {
+; CHECK-LABEL: define float @test_log2f_pos(
+; CHECK-SAME: float [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt float [[F]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.log2.f32(float [[F]])
+; CHECK-NEXT:    ret float [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret float 0.000000e+00
+;
+entry:
+  %isinf = fcmp ole float %f, 0x0000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call float @log2f(float %f)
+  ret float %call
+
+return:
+  ret float 0.0
+}
+
+define double @test_log2_pos(double %f) {
+; CHECK-LABEL: define double @test_log2_pos(
+; CHECK-SAME: double [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call double @llvm.log2.f64(double [[F]])
+; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret double 0.000000e+00
+;
+entry:
+  %isinf = fcmp ole double %f, 0x0000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call double @log2(double %f)
+  ret double %call
+
+return:
+  ret double 0.0
+}
+
+define fp128 @test_log2l_pos(fp128 %f) {
+; CHECK-LABEL: define fp128 @test_log2l_pos(
+; CHECK-SAME: fp128 [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt fp128 [[F]], 0xL00000000000000000000000000000000
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call fp128 @llvm.log2.f128(fp128 [[F]])
+; CHECK-NEXT:    ret fp128 [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret fp128 0xL00000000000000000000000000000000
+;
+entry:
+  %isinf = fcmp ole fp128 %f, 0xL00000000000000000000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call fp128 @log2l(fp128 %f)
+  ret fp128 %call
+
+return:
+  ret fp128 0xL00000000000000000000000000000000
+}
+
+
+define double @test_logb_pos(double %f) {
+; CHECK-LABEL: define double @test_logb_pos(
+; CHECK-SAME: double [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call double @logb(double [[F]])
+; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret double 0.000000e+00
+;
+entry:
+  %isinf = fcmp ole double %f, 0x0000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call double @logb(double %f)
+  ret double %call
+
+return:
+  ret double 0.0
+}
+
+define double @test_log1p_pos(double %f) {
+; CHECK-LABEL: define double @test_log1p_pos(
+; CHECK-SAME: double [[F:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ISINF:%.*]] = fcmp ugt double [[F]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[ISINF]], label [[IF_END:%.*]], label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = tail call double @log1p(double [[F]])
+; CHECK-NEXT:    ret double [[CALL]]
+; CHECK:       return:
+; CHECK-NEXT:    ret double 0.000000e+00
+;
+entry:
+  %isinf = fcmp ole double %f, 0x0000000000000000
+  br i1 %isinf, label %return, label %if.end
+
+if.end:
+  %call = tail call double @log1p(double %f)
+  ret double %call
+
+return:
+  ret double 0.0
+}
+
+declare double @log(double)
+declare float @logf(float)
+declare fp128 @logl(fp128)
+declare double @log10(double)
+declare float @log10f(float)
+declare fp128 @log10l(fp128)
+declare double @log2(double)
+declare float @log2f(float)
+declare fp128 @log2l(fp128)
+declare double @logb(double)
+declare double @log1p(double)



More information about the llvm-commits mailing list