Index: llvm/trunk/lib/Analysis/ConstantFolding.cpp =================================================================== --- llvm/trunk/lib/Analysis/ConstantFolding.cpp +++ llvm/trunk/lib/Analysis/ConstantFolding.cpp @@ -1438,6 +1438,36 @@ 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 @@ 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 @@ (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 @@ 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 @@ (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 @@ 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(Operands[1])) { if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy()) Index: llvm/trunk/test/Transforms/ConstProp/calls-math-finite.ll =================================================================== --- llvm/trunk/test/Transforms/ConstProp/calls-math-finite.ll +++ llvm/trunk/test/Transforms/ConstProp/calls-math-finite.ll @@ -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 ___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 +}