forked from OSchip/llvm-project
[ConstantFolding] Add folding for various math '__<func>_finite' routines generated from -ffast-math
Patch by Chris Chrulski Differential Revision: https://reviews.llvm.org/D31788 llvm-svn: 302956
This commit is contained in:
parent
3cd8c16d7f
commit
f7c864f89c
|
@ -1438,6 +1438,36 @@ bool llvm::canConstantFoldCallTo(const Function *F) {
|
|||
Name == "sinf" || Name == "sinhf" || Name == "sqrtf";
|
||||
case 't':
|
||||
return Name == "tan" || Name == "tanh" || Name == "tanf" || Name == "tanhf";
|
||||
case '_':
|
||||
|
||||
// Check for various function names that get used for the math functions
|
||||
// when the header files are preprocessed with the macro
|
||||
// __FINITE_MATH_ONLY__ enabled.
|
||||
// The '12' here is the length of the shortest name that can match.
|
||||
// We need to check the size before looking at Name[1] and Name[2]
|
||||
// so we may as well check a limit that will eliminate mismatches.
|
||||
if (Name.size() < 12 || Name[1] != '_')
|
||||
return false;
|
||||
switch (Name[2]) {
|
||||
default:
|
||||
return false;
|
||||
case 'a':
|
||||
return Name == "__acos_finite" || Name == "__acosf_finite" ||
|
||||
Name == "__asin_finite" || Name == "__asinf_finite" ||
|
||||
Name == "__atan2_finite" || Name == "__atan2f_finite";
|
||||
case 'c':
|
||||
return Name == "__cosh_finite" || Name == "__coshf_finite";
|
||||
case 'e':
|
||||
return Name == "__exp_finite" || Name == "__expf_finite" ||
|
||||
Name == "__exp2_finite" || Name == "__exp2f_finite";
|
||||
case 'l':
|
||||
return Name == "__log_finite" || Name == "__logf_finite" ||
|
||||
Name == "__log10_finite" || Name == "__log10f_finite";
|
||||
case 'p':
|
||||
return Name == "__pow_finite" || Name == "__powf_finite";
|
||||
case 's':
|
||||
return Name == "__sinh_finite" || Name == "__sinhf_finite";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1637,13 +1667,21 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
|
|||
if (!TLI)
|
||||
return nullptr;
|
||||
|
||||
switch (Name[0]) {
|
||||
char NameKeyChar = Name[0];
|
||||
if (Name[0] == '_' && Name.size() > 2 && Name[1] == '_')
|
||||
NameKeyChar = Name[2];
|
||||
|
||||
switch (NameKeyChar) {
|
||||
case 'a':
|
||||
if ((Name == "acos" && TLI->has(LibFunc_acos)) ||
|
||||
(Name == "acosf" && TLI->has(LibFunc_acosf)))
|
||||
(Name == "acosf" && TLI->has(LibFunc_acosf)) ||
|
||||
(Name == "__acos_finite" && TLI->has(LibFunc_acos_finite)) ||
|
||||
(Name == "__acosf_finite" && TLI->has(LibFunc_acosf_finite)))
|
||||
return ConstantFoldFP(acos, V, Ty);
|
||||
else if ((Name == "asin" && TLI->has(LibFunc_asin)) ||
|
||||
(Name == "asinf" && TLI->has(LibFunc_asinf)))
|
||||
(Name == "asinf" && TLI->has(LibFunc_asinf)) ||
|
||||
(Name == "__asin_finite" && TLI->has(LibFunc_asin_finite)) ||
|
||||
(Name == "__asinf_finite" && TLI->has(LibFunc_asinf_finite)))
|
||||
return ConstantFoldFP(asin, V, Ty);
|
||||
else if ((Name == "atan" && TLI->has(LibFunc_atan)) ||
|
||||
(Name == "atanf" && TLI->has(LibFunc_atanf)))
|
||||
|
@ -1657,15 +1695,21 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
|
|||
(Name == "cosf" && TLI->has(LibFunc_cosf)))
|
||||
return ConstantFoldFP(cos, V, Ty);
|
||||
else if ((Name == "cosh" && TLI->has(LibFunc_cosh)) ||
|
||||
(Name == "coshf" && TLI->has(LibFunc_coshf)))
|
||||
(Name == "coshf" && TLI->has(LibFunc_coshf)) ||
|
||||
(Name == "__cosh_finite" && TLI->has(LibFunc_cosh_finite)) ||
|
||||
(Name == "__coshf_finite" && TLI->has(LibFunc_coshf_finite)))
|
||||
return ConstantFoldFP(cosh, V, Ty);
|
||||
break;
|
||||
case 'e':
|
||||
if ((Name == "exp" && TLI->has(LibFunc_exp)) ||
|
||||
(Name == "expf" && TLI->has(LibFunc_expf)))
|
||||
(Name == "expf" && TLI->has(LibFunc_expf)) ||
|
||||
(Name == "__exp_finite" && TLI->has(LibFunc_exp_finite)) ||
|
||||
(Name == "__expf_finite" && TLI->has(LibFunc_expf_finite)))
|
||||
return ConstantFoldFP(exp, V, Ty);
|
||||
if ((Name == "exp2" && TLI->has(LibFunc_exp2)) ||
|
||||
(Name == "exp2f" && TLI->has(LibFunc_exp2f)))
|
||||
(Name == "exp2f" && TLI->has(LibFunc_exp2f)) ||
|
||||
(Name == "__exp2_finite" && TLI->has(LibFunc_exp2_finite)) ||
|
||||
(Name == "__exp2f_finite" && TLI->has(LibFunc_exp2f_finite)))
|
||||
// Constant fold exp2(x) as pow(2,x) in case the host doesn't have a
|
||||
// C99 library.
|
||||
return ConstantFoldBinaryFP(pow, 2.0, V, Ty);
|
||||
|
@ -1680,10 +1724,18 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
|
|||
break;
|
||||
case 'l':
|
||||
if ((Name == "log" && V > 0 && TLI->has(LibFunc_log)) ||
|
||||
(Name == "logf" && V > 0 && TLI->has(LibFunc_logf)))
|
||||
(Name == "logf" && V > 0 && TLI->has(LibFunc_logf)) ||
|
||||
(Name == "__log_finite" && V > 0 &&
|
||||
TLI->has(LibFunc_log_finite)) ||
|
||||
(Name == "__logf_finite" && V > 0 &&
|
||||
TLI->has(LibFunc_logf_finite)))
|
||||
return ConstantFoldFP(log, V, Ty);
|
||||
else if ((Name == "log10" && V > 0 && TLI->has(LibFunc_log10)) ||
|
||||
(Name == "log10f" && V > 0 && TLI->has(LibFunc_log10f)))
|
||||
(Name == "log10f" && V > 0 && TLI->has(LibFunc_log10f)) ||
|
||||
(Name == "__log10_finite" && V > 0 &&
|
||||
TLI->has(LibFunc_log10_finite)) ||
|
||||
(Name == "__log10f_finite" && V > 0 &&
|
||||
TLI->has(LibFunc_log10f_finite)))
|
||||
return ConstantFoldFP(log10, V, Ty);
|
||||
break;
|
||||
case 'r':
|
||||
|
@ -1695,7 +1747,9 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
|
|||
(Name == "sinf" && TLI->has(LibFunc_sinf)))
|
||||
return ConstantFoldFP(sin, V, Ty);
|
||||
else if ((Name == "sinh" && TLI->has(LibFunc_sinh)) ||
|
||||
(Name == "sinhf" && TLI->has(LibFunc_sinhf)))
|
||||
(Name == "sinhf" && TLI->has(LibFunc_sinhf)) ||
|
||||
(Name == "__sinh_finite" && TLI->has(LibFunc_sinh_finite)) ||
|
||||
(Name == "__sinhf_finite" && TLI->has(LibFunc_sinhf_finite)))
|
||||
return ConstantFoldFP(sinh, V, Ty);
|
||||
else if ((Name == "sqrt" && V >= 0 && TLI->has(LibFunc_sqrt)) ||
|
||||
(Name == "sqrtf" && V >= 0 && TLI->has(LibFunc_sqrtf)))
|
||||
|
@ -1813,13 +1867,17 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
|
|||
if (!TLI)
|
||||
return nullptr;
|
||||
if ((Name == "pow" && TLI->has(LibFunc_pow)) ||
|
||||
(Name == "powf" && TLI->has(LibFunc_powf)))
|
||||
(Name == "powf" && TLI->has(LibFunc_powf)) ||
|
||||
(Name == "__pow_finite" && TLI->has(LibFunc_pow_finite)) ||
|
||||
(Name == "__powf_finite" && TLI->has(LibFunc_powf_finite)))
|
||||
return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty);
|
||||
if ((Name == "fmod" && TLI->has(LibFunc_fmod)) ||
|
||||
(Name == "fmodf" && TLI->has(LibFunc_fmodf)))
|
||||
return ConstantFoldBinaryFP(fmod, Op1V, Op2V, Ty);
|
||||
if ((Name == "atan2" && TLI->has(LibFunc_atan2)) ||
|
||||
(Name == "atan2f" && TLI->has(LibFunc_atan2f)))
|
||||
(Name == "atan2f" && TLI->has(LibFunc_atan2f)) ||
|
||||
(Name == "__atan2_finite" && TLI->has(LibFunc_atan2_finite)) ||
|
||||
(Name == "__atan2f_finite" && TLI->has(LibFunc_atan2f_finite)))
|
||||
return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty);
|
||||
} else if (auto *Op2C = dyn_cast<ConstantInt>(Operands[1])) {
|
||||
if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy())
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
; RUN: opt < %s -constprop -S | FileCheck %s
|
||||
|
||||
; Test to verify constant folding can occur when math
|
||||
; routines are mapped to the __<func>_finite versions
|
||||
; of functions due to __FINITE_MATH_ONLY__ being
|
||||
; enabled on headers. All calls should constant
|
||||
; fold away in this test.
|
||||
|
||||
declare double @__acos_finite(double) #0
|
||||
declare float @__acosf_finite(float) #0
|
||||
declare double @__asin_finite(double) #0
|
||||
declare float @__asinf_finite(float) #0
|
||||
declare double @__atan2_finite(double, double) #0
|
||||
declare float @__atan2f_finite(float, float) #0
|
||||
declare double @__cosh_finite(double) #0
|
||||
declare float @__coshf_finite(float) #0
|
||||
declare double @__exp2_finite(double) #0
|
||||
declare float @__exp2f_finite(float) #0
|
||||
declare double @__exp_finite(double) #0
|
||||
declare float @__expf_finite(float) #0
|
||||
declare double @__log10_finite(double) #0
|
||||
declare float @__log10f_finite(float) #0
|
||||
declare double @__log_finite(double) #0
|
||||
declare float @__logf_finite(float) #0
|
||||
declare double @__pow_finite(double, double) #0
|
||||
declare float @__powf_finite(float, float) #0
|
||||
declare double @__sinh_finite(double) #0
|
||||
declare float @__sinhf_finite(float) #0
|
||||
|
||||
attributes #0 = { nounwind readnone }
|
||||
|
||||
define void @T() {
|
||||
; CHECK-LABEL: @T(
|
||||
|
||||
; CHECK-NOT: call
|
||||
; CHECK: ret
|
||||
|
||||
%slot = alloca double
|
||||
%slotf = alloca float
|
||||
|
||||
%ACOS = call fast double @__acos_finite(double 1.000000e+00)
|
||||
store double %ACOS, double* %slot
|
||||
%ASIN = call fast double @__asin_finite(double 1.000000e+00)
|
||||
store double %ASIN, double* %slot
|
||||
%ATAN2 = call fast double @__atan2_finite(double 3.000000e+00, double 4.000000e+00)
|
||||
store double %ATAN2, double* %slot
|
||||
%COSH = call fast double @__cosh_finite(double 3.000000e+00)
|
||||
store double %COSH, double* %slot
|
||||
%EXP = call fast double @__exp_finite(double 3.000000e+00)
|
||||
store double %EXP, double* %slot
|
||||
%EXP2 = call fast double @__exp2_finite(double 3.000000e+00)
|
||||
store double %EXP2, double* %slot
|
||||
%LOG = call fast double @__log_finite(double 3.000000e+00)
|
||||
store double %LOG, double* %slot
|
||||
%LOG10 = call fast double @__log10_finite(double 3.000000e+00)
|
||||
store double %LOG10, double* %slot
|
||||
%POW = call fast double @__pow_finite(double 1.000000e+00, double 4.000000e+00)
|
||||
store double %POW, double* %slot
|
||||
%SINH = call fast double @__sinh_finite(double 3.000000e+00)
|
||||
store double %SINH, double* %slot
|
||||
|
||||
%ACOSF = call fast float @__acosf_finite(float 1.000000e+00)
|
||||
store float %ACOSF, float* %slotf
|
||||
%ASINF = call fast float @__asinf_finite(float 1.000000e+00)
|
||||
store float %ASINF, float* %slotf
|
||||
%ATAN2F = call fast float @__atan2f_finite(float 3.000000e+00, float 4.000000e+00)
|
||||
store float %ATAN2F, float* %slotf
|
||||
%COSHF = call fast float @__coshf_finite(float 3.000000e+00)
|
||||
store float %COSHF, float* %slotf
|
||||
%EXPF = call fast float @__expf_finite(float 3.000000e+00)
|
||||
store float %EXPF, float* %slotf
|
||||
%EXP2F = call fast float @__exp2f_finite(float 3.000000e+00)
|
||||
store float %EXP2F, float* %slotf
|
||||
%LOGF = call fast float @__logf_finite(float 3.000000e+00)
|
||||
store float %LOGF, float* %slotf
|
||||
%LOG10F = call fast float @__log10f_finite(float 3.000000e+00)
|
||||
store float %LOG10F, float* %slotf
|
||||
%POWF = call fast float @__powf_finite(float 3.000000e+00, float 4.000000e+00)
|
||||
store float %POWF, float* %slotf
|
||||
%SINHF = call fast float @__sinhf_finite(float 3.000000e+00)
|
||||
store float %SINHF, float* %slotf
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue