Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Oct 10, 2024

Conversation

davemgreen
Copy link
Collaborator

Similar to 112aac4, 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.


// 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);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unrelated, I'll push it separately.

@llvmbot
Copy link
Member

llvmbot commented Oct 7, 2024

@llvm/pr-subscribers-llvm-transforms

Author: David Green (davemgreen)

Changes

Similar to 112aac4, 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.


Full diff: https://github.com/llvm/llvm-project/pull/111428.diff

4 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+32-17)
  • (modified) llvm/test/Transforms/InstCombine/double-float-shrink-1.ll (+11-10)
  • (modified) llvm/test/Transforms/InstCombine/log-pow.ll (+3-3)
  • (added) llvm/test/Transforms/InstCombine/log-to-intrinsic.ll (+279)
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)

@arsenm arsenm added the floating-point Floating-point math label Oct 7, 2024
@davemgreen davemgreen force-pushed the gh-ic-logtointrinsic branch from 493cea5 to 41ded02 Compare October 8, 2024 14:01
Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with nits

Comment on lines 2598 to 2600
Function *F = Log->getParent()->getParent();
IsKnownNoErrno = Known.isKnownNeverLogicalZero(*F, Ty) &&
Known.cannotBeOrderedLessThanZero();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Function *F = Log->getParent()->getParent();
IsKnownNoErrno = Known.isKnownNeverLogicalZero(*F, Ty) &&
Known.cannotBeOrderedLessThanZero();
Function *F = Log->getParent()->getParent();
IsKnownNoErrno = Known.cannotBeOrderedLessThanZero() &&
Known.isKnownNeverLogicalZero(*F, Ty);

llvm/test/Transforms/InstCombine/log-to-intrinsic.ll Outdated Show resolved Hide resolved
Similar to 112aac4, 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.
@davemgreen davemgreen force-pushed the gh-ic-logtointrinsic branch from 41ded02 to 1268da3 Compare October 9, 2024 09:43
@davemgreen davemgreen merged commit 5184d76 into llvm:main Oct 10, 2024
9 checks passed
@davemgreen davemgreen deleted the gh-ic-logtointrinsic branch October 10, 2024 08:54
@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 10, 2024

LLVM Buildbot has detected a new failure on builder sanitizer-x86_64-linux-qemu running on sanitizer-buildbot3 while building llvm at step 2 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/139/builds/4826

Here is the relevant piece of the build log for the reference
Step 2 (annotate) failure: 'python ../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py' (failure) (timed out)
...
[    5.336443] pci 0000:00:00.0: [8086:29c0] type 00 class 0x060000 conventional PCI endpoint
[    5.353818] pci 0000:00:01.0: [1234:1111] type 00 class 0x030000 conventional PCI endpoint
[    5.356443] pci 0000:00:01.0: BAR 0 [mem 0xfd000000-0xfdffffff pref]
[    5.360443] pci 0000:00:01.0: BAR 2 [mem 0xfebf0000-0xfebf0fff]
[    5.370549] pci 0000:00:01.0: ROM [mem 0xfebe0000-0xfebeffff pref]
[    5.371443] pci 0000:00:01.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff]
[    5.371443] pci 0000:00:02.0: [8086:100e] type 00 class 0x020000 conventional PCI endpoint
[    5.372568] pci 0000:00:02.0: BAR 0 [mem 0xfebc0000-0xfebdffff]
[    5.374550] pci 0000:00:02.0: BAR 1 [io  0xc000-0xc03f]
+ ssh -p 62080 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ControlPersist=30m -M -S /home/b/sanitizer-x86_64-linux-qemu/build/qemu_tmp/ssh-control-socket -i /home/b/qemu_image/debian.id_rsa root@localhost 'uname -a'
command timed out: 1200 seconds without output running [b'python', b'../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py'], attempting to kill
process killed by signal 9
program finished with exit code -1
elapsedTime=3585.494199
Step 29 (start LAM QEMU) failure: start LAM QEMU (failure)
...
[    5.025751] cpuidle: using governor menu
[    5.051443] PCI: ECAM [mem 0xb0000000-0xbfffffff] (base 0xb0000000) for domain 0000 [bus 00-ff]
[    5.057647] PCI: ECAM [mem 0xb0000000-0xbfffffff] reserved as E820 entry
[    5.060443] PCI: Using configuration type 1 for base access
[    5.061443] mtrr: your CPUs had inconsistent fixed MTRR settings
[    5.061443] mtrr: your CPUs had inconsistent variable MTRR settings
[    5.061443] mtrr: your CPUs had inconsistent MTRRdefType settings
[    5.061443] mtrr: probably your BIOS does not setup all CPUs.
[    5.061443] mtrr: corrected configuration.
[    5.069443] kprobes: kprobe jump-optimization is enabled. All kprobes are optimized if possible.
[    5.079540] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
[    5.080561] HugeTLB: 28 KiB vmemmap can be freed for a 2.00 MiB page
[    5.098443] ACPI: Added _OSI(Module Device)
[    5.098605] ACPI: Added _OSI(Processor Device)
[    5.099443] ACPI: Added _OSI(3.0 _SCP Extensions)
[    5.099443] ACPI: Added _OSI(Processor Aggregator Device)
[    5.136577] ACPI: 1 ACPI AML tables successfully acquired and loaded
[    5.217658] ACPI: Interpreter enabled
[    5.221857] ACPI: PM: (supports S0 S3 S4 S5)
[    5.222443] ACPI: Using IOAPIC for interrupt routing
[    5.225443] PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug
[    5.225443] PCI: Using E820 reservations for host bridge windows
[    5.226443] ACPI: Enabled 2 GPEs in block 00 to 3F
[    5.307757] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
[    5.311723] acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI HPX-Type3]
[    5.313443] acpi PNP0A08:00: _OSC: platform does not support [LTR]
[    5.313443] acpi PNP0A08:00: _OSC: OS now controls [PME PCIeCapability]
[    5.330644] PCI host bridge to bus 0000:00
[    5.331443] pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
[    5.331443] pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
[    5.331443] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window]
[    5.331443] pci_bus 0000:00: root bus resource [mem 0x80000000-0xafffffff window]
[    5.331443] pci_bus 0000:00: root bus resource [mem 0xc0000000-0xfebfffff window]
[    5.331443] pci_bus 0000:00: root bus resource [mem 0x480000000-0xc7fffffff window]
[    5.331865] pci_bus 0000:00: root bus resource [bus 00-ff]
[    5.336443] pci 0000:00:00.0: [8086:29c0] type 00 class 0x060000 conventional PCI endpoint
[    5.353818] pci 0000:00:01.0: [1234:1111] type 00 class 0x030000 conventional PCI endpoint
[    5.356443] pci 0000:00:01.0: BAR 0 [mem 0xfd000000-0xfdffffff pref]
[    5.360443] pci 0000:00:01.0: BAR 2 [mem 0xfebf0000-0xfebf0fff]
[    5.370549] pci 0000:00:01.0: ROM [mem 0xfebe0000-0xfebeffff pref]
[    5.371443] pci 0000:00:01.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff]
[    5.371443] pci 0000:00:02.0: [8086:100e] type 00 class 0x020000 conventional PCI endpoint
[    5.372568] pci 0000:00:02.0: BAR 0 [mem 0xfebc0000-0xfebdffff]
[    5.374550] pci 0000:00:02.0: BAR 1 [io  0xc000-0xc03f]
+ ssh -p 62080 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ControlPersist=30m -M -S /home/b/sanitizer-x86_64-linux-qemu/build/qemu_tmp/ssh-control-socket -i /home/b/qemu_image/debian.id_rsa root@localhost 'uname -a'

command timed out: 1200 seconds without output running [b'python', b'../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py'], attempting to kill
process killed by signal 9
program finished with exit code -1
elapsedTime=3585.494199

DanielCChen pushed a commit to DanielCChen/llvm-project that referenced this pull request Oct 16, 2024
…e. (llvm#111428)

Similar to 112aac4, 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants