Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions llvm/lib/Analysis/ConstantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include <cassert>
#include <cerrno>
#include <cfenv>
#include <cfloat>
#include <cmath>
#include <cstdint>

Expand Down Expand Up @@ -1698,9 +1699,9 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
Name == "sinh" || Name == "sinhf" ||
Name == "sqrt" || Name == "sqrtf";
case 't':
return Name == "tan" || Name == "tanf" ||
Name == "tanh" || Name == "tanhf" ||
Name == "trunc" || Name == "truncf";
return Name == "tan" || Name == "tanf" || Name == "tanh" ||
Name == "tanhf" || Name == "trunc" || Name == "truncf" ||
Name == "tgamma" || Name == "tgammaf";
case '_':
// Check for various function names that get used for the math functions
// when the header files are preprocessed with the macro
Expand Down Expand Up @@ -2417,6 +2418,14 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
if (TLI->has(Func))
return ConstantFoldFP(erf, APF, Ty);
break;
case LibFunc_tgamma:
case LibFunc_tgammaf:
// NOTE: These boundaries are somewhat conservative.
if (TLI->has(Func) &&
(Ty->isDoubleTy() && APF > APFloat(DBL_MIN) && APF < APFloat(171.0) ||
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that 1 / DBL_MAX < DBL_MIN, and we don't want to constant fold subnormal floating point as a parameter. I believe using MIN will be sufficient.

Copy link
Contributor

Choose a reason for hiding this comment

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

we don't want to constant fold subnormal floating point as a parameter.

Yes we do

Ty->isFloatTy() && APF > APFloat(FLT_MIN) && APF < APFloat(35.0f)))
return ConstantFoldFP(tgamma, APF, Ty);
break;
case LibFunc_nearbyint:
case LibFunc_nearbyintf:
case LibFunc_rint:
Expand Down Expand Up @@ -3629,6 +3638,10 @@ bool llvm::isMathLibCallNoop(const CallBase *Call,
case LibFunc_sqrtf:
return Op.isNaN() || Op.isZero() || !Op.isNegative();

case LibFunc_tgamma:
case LibFunc_tgammaf:
return true;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since we explicitly limit the input range, it should be safe to return true here. Ideally, this function could be integrated into the constant folding process.


// FIXME: Add more functions: sqrt_finite, atanh, expm1, log1p,
// maybe others?
default:
Expand Down
255 changes: 255 additions & 0 deletions llvm/test/Transforms/InstCombine/tgamma.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

define float @tgammaf_in_range() {
; CHECK-LABEL: define float @tgammaf_in_range() {
; CHECK-NEXT: ret float 0x479A216280000000
;
%r = call float @tgammaf(float 34.0)
ret float %r
}

define double @tgamma_in_range() {
; CHECK-LABEL: define double @tgamma_in_range() {
; CHECK-NEXT: ret double 0x605166C698CF183B
;
%r = call double @tgamma(double 100.0)
ret double %r
}

define float @tgammaf_const_left_range() {
; CHECK-LABEL: define float @tgammaf_const_left_range() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 0x3810000000000000)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 0x3810000000000000)
ret float %r
}

define double @tgamma_const_left_range() {
; CHECK-LABEL: define double @tgamma_const_left_range() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 0x10000000000000)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 0x0010000000000000)
ret double %r
}

define float @tgammaf_const_right_range() {
; CHECK-LABEL: define float @tgammaf_const_right_range() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 3.600000e+01)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 36.0)
ret float %r
}

define double @tgamma_const_right_range() {
; CHECK-LABEL: define double @tgamma_const_right_range() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 1.720000e+02)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 172.0)
ret double %r
}

define float @tgammaf_minus_one() {
; CHECK-LABEL: define float @tgammaf_minus_one() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float -1.000000e+00)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float -1.000000e+00)
ret float %r
}

define double @tgamma_minus_one() {
; CHECK-LABEL: define double @tgamma_minus_one() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double -1.000000e+00)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double -1.000000e+00)
ret double %r
}

define float @tgammaf_minus_one_memory_none() {
; CHECK-LABEL: define float @tgammaf_minus_one_memory_none() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float -1.000000e+00) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float -1.000000e+00) readnone
ret float %r
}

define double @tgamma_minus_one_memory_none() {
; CHECK-LABEL: define double @tgamma_minus_one_memory_none() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double -1.000000e+00) #[[ATTR1]]
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double -1.000000e+00) readnone
ret double %r
}

define float @tgammaf_zero() {
; CHECK-LABEL: define float @tgammaf_zero() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 0.000000e+00)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 0.000000e+00)
ret float %r
}

define double @tgamma_zero() {
; CHECK-LABEL: define double @tgamma_zero() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 0.000000e+00)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 0.000000e+00)
ret double %r
}

define float @tgammaf_neg_zero() {
; CHECK-LABEL: define float @tgammaf_neg_zero() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float -0.000000e+00)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float -0.000000e+00)
ret float %r
}

define double @tgamma_neg_zero() {
; CHECK-LABEL: define double @tgamma_neg_zero() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double -0.000000e+00)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double -0.000000e+00)
ret double %r
}

define float @tgammaf_inf() {
; CHECK-LABEL: define float @tgammaf_inf() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 0x7FF0000000000000)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 0x7FF0000000000000)
ret float %r
}

define double @tgamma_inf() {
; CHECK-LABEL: define double @tgamma_inf() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 0x7FF0000000000000)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 0x7FF0000000000000)
ret double %r
}

define float @tgammaf_inf_memory_none() {
; CHECK-LABEL: define float @tgammaf_inf_memory_none() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 0x7FF0000000000000) #[[ATTR1]]
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 0x7FF0000000000000) readnone
ret float %r
}

define double @tgamma_inf_memory_none() {
; CHECK-LABEL: define double @tgamma_inf_memory_none() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 0x7FF0000000000000) #[[ATTR1]]
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 0x7FF0000000000000) readnone
ret double %r
}

define float @tgammaf_neg_inf() {
; CHECK-LABEL: define float @tgammaf_neg_inf() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 0xFFF0000000000000)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 0xFFF0000000000000)
ret float %r
}

define double @tgamma_neg_inf() {
; CHECK-LABEL: define double @tgamma_neg_inf() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 0xFFF0000000000000)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 0xFFF0000000000000)
ret double %r
}

define float @tgammaf_neg_inf_memory_none() {
; CHECK-LABEL: define float @tgammaf_neg_inf_memory_none() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 0xFFF0000000000000) #[[ATTR1]]
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 0xFFF0000000000000) readnone
ret float %r
}

define double @tgamma_neg_inf_memory_none() {
; CHECK-LABEL: define double @tgamma_neg_inf_memory_none() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 0xFFF0000000000000) #[[ATTR1]]
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 0xFFF0000000000000) readnone
ret double %r
}

define float @tgammaf_nan() {
; CHECK-LABEL: define float @tgammaf_nan() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 0x7FF8000000000000)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 0x7FF8000000000000)
ret float %r
}

define double @tgamma_nan() {
; CHECK-LABEL: define double @tgamma_nan() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 0x7FF8000000000000)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 0x7FF8000000000000)
ret double %r
}

define float @tgammaf_nan_memory_none() {
; CHECK-LABEL: define float @tgammaf_nan_memory_none() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float 0x7FF8000000000000) #[[ATTR1]]
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float 0x7FF8000000000000) readnone
ret float %r
}

define double @tgamma_nan_memory_none() {
; CHECK-LABEL: define double @tgamma_nan_memory_none() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double 0x7FF8000000000000) #[[ATTR1]]
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double 0x7FF8000000000000) readnone
ret double %r
}

define float @tgammaf_poison() {
; CHECK-LABEL: define float @tgammaf_poison() {
; CHECK-NEXT: [[R:%.*]] = call float @tgammaf(float poison)
; CHECK-NEXT: ret float [[R]]
;
%r = call float @tgammaf(float poison)
ret float %r
}

define double @tgamma_poison() {
; CHECK-LABEL: define double @tgamma_poison() {
; CHECK-NEXT: [[R:%.*]] = call double @tgamma(double poison)
; CHECK-NEXT: ret double [[R]]
;
%r = call double @tgamma(double poison)
ret double %r
}

declare float @tgammaf(float) willreturn
declare double @tgamma(double) willreturn
Loading