Commit f7657db9 by Kaveh R. Ghazi Committed by Kaveh Ghazi

builtins.c (real_dconstp, [...]): New, split out from fold_builtin.

	* builtins.c (real_dconstp, fold_builtin_logarithm,
	fold_builtin_exponent): New, split out from fold_builtin.  Also
	generalize to add log2, log10, exp2 and exp10/pow10 equivalents.
	* emit-rtl.c (dconst3, dconst10, dconstthird): New.
	(init_emit_once): Initialize new dconsts, use ARRAY_SIZE in lieu
	of hardcoded array size.
	* fold-const.c (fold): Add cases for exp2, exp10 and pow10.
	(tree_expr_nonnegative_p): Likewise.
	* real.h (dconst3, dconst10, dconstthird): New.

testsuite:
	* gcc.dg/torture/builtin-explog-1.c: New testcase.

From-SVN: r71252
parent dcbdd9cc
2003-09-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (real_dconstp, fold_builtin_logarithm,
fold_builtin_exponent): New, split out from fold_builtin. Also
generalize to add log2, log10, exp2 and exp10/pow10 equivalents.
* emit-rtl.c (dconst3, dconst10, dconstthird): New.
(init_emit_once): Initialize new dconsts, use ARRAY_SIZE in lieu
of hardcoded array size.
* fold-const.c (fold): Add cases for exp2, exp10 and pow10.
(tree_expr_nonnegative_p): Likewise.
* real.h (dconst3, dconst10, dconstthird): New.
Tue Sep 9 22:18:48 CEST 2003 Jan Hubicka <jh@suse.cz>
* cgraphunit.c (cgraph_finalize_function): Fix handling of extern
......
......@@ -110,9 +110,12 @@ rtx const_true_rtx;
REAL_VALUE_TYPE dconst0;
REAL_VALUE_TYPE dconst1;
REAL_VALUE_TYPE dconst2;
REAL_VALUE_TYPE dconst3;
REAL_VALUE_TYPE dconst10;
REAL_VALUE_TYPE dconstm1;
REAL_VALUE_TYPE dconstm2;
REAL_VALUE_TYPE dconsthalf;
REAL_VALUE_TYPE dconstthird;
/* All references to the following fixed hard registers go through
these unique rtl objects. On machines where the frame-pointer and
......@@ -5414,13 +5417,17 @@ init_emit_once (int line_numbers)
REAL_VALUE_FROM_INT (dconst0, 0, 0, double_mode);
REAL_VALUE_FROM_INT (dconst1, 1, 0, double_mode);
REAL_VALUE_FROM_INT (dconst2, 2, 0, double_mode);
REAL_VALUE_FROM_INT (dconst3, 3, 0, double_mode);
REAL_VALUE_FROM_INT (dconst10, 10, 0, double_mode);
REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode);
REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode);
dconsthalf = dconst1;
dconsthalf.exp--;
for (i = 0; i <= 2; i++)
real_arithmetic (&dconstthird, RDIV_EXPR, &dconst1, &dconst3);
for (i = 0; i < (int) ARRAY_SIZE (const_tiny_rtx); i++)
{
REAL_VALUE_TYPE *r =
(i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
......
......@@ -6110,10 +6110,20 @@ fold (tree expr)
return build_function_call_expr (sqrtfn, arglist);
}
/* Optimize exp(x)*exp(y) as exp(x+y). */
if ((fcode0 == BUILT_IN_EXP && fcode1 == BUILT_IN_EXP)
|| (fcode0 == BUILT_IN_EXPF && fcode1 == BUILT_IN_EXPF)
|| (fcode0 == BUILT_IN_EXPL && fcode1 == BUILT_IN_EXPL))
/* Optimize expN(x)*expN(y) as expN(x+y). */
if (fcode0 == fcode1
&& (fcode0 == BUILT_IN_EXP
|| fcode0 == BUILT_IN_EXPF
|| fcode0 == BUILT_IN_EXPL
|| fcode0 == BUILT_IN_EXP2
|| fcode0 == BUILT_IN_EXP2F
|| fcode0 == BUILT_IN_EXP2L
|| fcode0 == BUILT_IN_EXP10
|| fcode0 == BUILT_IN_EXP10F
|| fcode0 == BUILT_IN_EXP10L
|| fcode0 == BUILT_IN_POW10
|| fcode0 == BUILT_IN_POW10F
|| fcode0 == BUILT_IN_POW10L))
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
tree arg = build (PLUS_EXPR, type,
......@@ -6445,10 +6455,19 @@ fold (tree expr)
if (flag_unsafe_math_optimizations)
{
enum built_in_function fcode = builtin_mathfn_code (arg1);
/* Optimize x/exp(y) into x*exp(-y). */
/* Optimize x/expN(y) into x*expN(-y). */
if (fcode == BUILT_IN_EXP
|| fcode == BUILT_IN_EXPF
|| fcode == BUILT_IN_EXPL)
|| fcode == BUILT_IN_EXPL
|| fcode == BUILT_IN_EXP2
|| fcode == BUILT_IN_EXP2F
|| fcode == BUILT_IN_EXP2L
|| fcode == BUILT_IN_EXP10
|| fcode == BUILT_IN_EXP10F
|| fcode == BUILT_IN_EXP10L
|| fcode == BUILT_IN_POW10
|| fcode == BUILT_IN_POW10F
|| fcode == BUILT_IN_POW10L)
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
tree arg = build1 (NEGATE_EXPR, type,
......@@ -8674,6 +8693,15 @@ tree_expr_nonnegative_p (tree t)
case BUILT_IN_EXP:
case BUILT_IN_EXPF:
case BUILT_IN_EXPL:
case BUILT_IN_EXP2:
case BUILT_IN_EXP2F:
case BUILT_IN_EXP2L:
case BUILT_IN_EXP10:
case BUILT_IN_EXP10F:
case BUILT_IN_EXP10L:
case BUILT_IN_POW10:
case BUILT_IN_POW10F:
case BUILT_IN_POW10L:
case BUILT_IN_FABS:
case BUILT_IN_FABSF:
case BUILT_IN_FABSL:
......
......@@ -322,14 +322,17 @@ extern void real_ldexp (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
/* **** End of software floating point emulator interface macros **** */
/* Constant real values 0, 1, 2, -1, -2 and 0.5. */
/* Constant real values 0, 1, 2, 3, 10, -1, -2, 0.5 and 1/3. */
extern REAL_VALUE_TYPE dconst0;
extern REAL_VALUE_TYPE dconst1;
extern REAL_VALUE_TYPE dconst2;
extern REAL_VALUE_TYPE dconst3;
extern REAL_VALUE_TYPE dconst10;
extern REAL_VALUE_TYPE dconstm1;
extern REAL_VALUE_TYPE dconstm2;
extern REAL_VALUE_TYPE dconsthalf;
extern REAL_VALUE_TYPE dconstthird;
/* Function to return a real value (not a tree node)
from a given integer constant. */
......
2003-09-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/torture/builtin-explog-1.c: New testcase.
2003-09-08 Mark Mitchell <mark@codesourcery.com>
* gcc.dg/ia64-types1.c: New test.
......
/* Copyright (C) 2003 Free Software Foundation.
Verify that built-in math function constant folding of log & exp is
correctly performed by the compiler.
Written by Kaveh Ghazi, 2003-09-05. */
/* { dg-do link } */
/* { dg-options "-ffast-math" } */
/* Define "e" with as many bits as found in builtins.c:dconste. */
#define M_E 2.7182818284590452353602874713526624977572470936999595749669676277241
#define M_EF 2.7182818284590452353602874713526624977572470936999595749669676277241F
#define M_EL 2.7182818284590452353602874713526624977572470936999595749669676277241L
/* Precision for comparison tests. */
#define PREC 0.0000001
#define PRECF 0.0001F
#define PRECL 0.0000000000001L
#define PROTOTYPE(FN) extern double FN(double); extern float FN##f(float); \
extern long double FN##l(long double);
#define PROTOTYPE2(FN) extern double FN(double, double); \
extern float FN##f(float, float); \
extern long double FN##l(long double, long double);
PROTOTYPE(exp)
PROTOTYPE(exp2)
PROTOTYPE(exp10)
PROTOTYPE(log)
PROTOTYPE(log2)
PROTOTYPE(log10)
PROTOTYPE(pow10)
PROTOTYPE(sqrt)
PROTOTYPE(cbrt)
PROTOTYPE2(pow)
void test(double d1, double d2, float f1, float f2,
long double ld1, long double ld2)
{
#define LOG_1(LOG) \
extern void link_failure_##LOG##_1(void); \
if (LOG(1.0) != 0.0 || LOG##f(1.0F) != 0.0F || LOG##l(1.0L) != 0.0L) \
link_failure_##LOG##_1()
LOG_1(log);
LOG_1(log2);
LOG_1(log10);
#define LOG_N(LOG, BASE) \
extern void link_failure_##LOG##_N(void); \
if (LOG(BASE) != 1.0 || LOG##f(BASE##F) != 1.0F || LOG##l(BASE##L) != 1.0L) \
link_failure_##LOG##_N()
LOG_N(log, M_E);
LOG_N(log2, 2.0);
LOG_N(log10, 10.0);
#define LOGEXP_SAME(LOG, EXP) \
extern void link_failure_##LOG##_##EXP##_same(void); \
if (LOG(EXP(d1)) != d1 || LOG##f(EXP##f(f1)) != f1 \
|| LOG##l(EXP##l(ld1)) != ld1) link_failure_##LOG##_##EXP##_same()
LOGEXP_SAME(log,exp);
LOGEXP_SAME(log2,exp2);
LOGEXP_SAME(log10,exp10);
LOGEXP_SAME(log10,pow10);
#define LOGEXP(LOG, EXP, BASE) \
extern void link_failure_##LOG##_##EXP(void); \
if (LOG(EXP(d1)) != d1*LOG(BASE) || LOG##f(EXP##f(f1)) != f1*LOG##f(BASE##F) \
|| LOG##l(EXP##l(ld1)) != ld1*LOG##l(BASE##L)) link_failure_##LOG##_##EXP()
LOGEXP(log,exp,M_E);
LOGEXP(log,exp2,2.0);
LOGEXP(log,exp10,10.0);
LOGEXP(log,pow10,10.0);
LOGEXP(log2,exp,M_E);
LOGEXP(log2,exp2,2.0);
LOGEXP(log2,exp10,10.0);
LOGEXP(log2,pow10,10.0);
LOGEXP(log10,exp,M_E);
LOGEXP(log10,exp2,2.0);
LOGEXP(log10,exp10,10.0);
LOGEXP(log10,pow10,10.0);
#define LOG_SQRT(LOG) \
extern void link_failure_##LOG##_sqrt(void); \
if (LOG(sqrt(d1)) != 0.5*LOG(d1) || LOG##f(sqrtf(f1)) != 0.5F*LOG##f(f1) \
|| LOG##l(sqrtl(ld1)) != 0.5L*LOG##l(ld1)) link_failure_##LOG##_sqrt()
LOG_SQRT(log);
LOG_SQRT(log2);
LOG_SQRT(log10);
#define LOG_CBRT(LOG) \
extern void link_failure_##LOG##_cbrt(void); \
if (LOG(cbrt(d1)) != (1.0/3)*LOG(d1) \
|| LOG##f(cbrtf(f1)) != (1.0F/3)*LOG##f(f1) \
|| LOG##l(cbrtl(ld1)) != (1.0L/3)*LOG##l(ld1)) link_failure_##LOG##_cbrt()
LOG_CBRT(log);
LOG_CBRT(log2);
LOG_CBRT(log10);
#define LOGPOW(LOG, POW) \
extern void link_failure_##LOG##_##POW(void); \
if (LOG(POW(d1,d2)) != d2*LOG(d1) || LOG##f(POW##f(f1,f2)) != f2*LOG##f(f1) \
|| LOG##l(POW##l(ld1,ld2)) != ld2*LOG##l(ld1)) link_failure_##LOG##_##POW()
LOGPOW(log,pow);
LOGPOW(log2,pow);
LOGPOW(log10,pow);
#define EXP_0(EXP) \
extern void link_failure_##EXP##_0(void); \
if (EXP(0.0) != 1.0 || EXP##f(0.0F) != 1.0F || EXP##l(0.0L) != 1.0L) \
link_failure_##EXP##_0()
EXP_0(exp);
EXP_0(exp2);
EXP_0(exp10);
EXP_0(pow10);
#define EXP_N(EXP, BASE) \
extern void link_failure_##EXP##_N(void); \
if (EXP(1.0) != BASE || EXP##f(1.0F) != BASE##F || EXP##l(1.0L) != BASE##L) \
link_failure_##EXP##_N()
EXP_N(exp, M_E);
EXP_N(exp2, 2.0);
EXP_N(exp10, 10.0);
EXP_N(pow10, 10.0);
#define EXP_INT(EXP, BASE) \
extern void link_failure_##EXP##_INT(void); \
if (EXP(5.0) < (BASE)*(BASE)*(BASE)*(BASE)*(BASE) - PREC \
|| EXP(5.0) > (BASE)*(BASE)*(BASE)*(BASE)*(BASE) + PREC \
|| EXP##f(5.0F) < (BASE##F)*(BASE##F)*(BASE##F)*(BASE##F)*(BASE##F) -PRECF \
|| EXP##f(5.0F) > (BASE##F)*(BASE##F)*(BASE##F)*(BASE##F)*(BASE##F) +PRECF \
|| EXP##l(5.0L) < (BASE##L)*(BASE##L)*(BASE##L)*(BASE##L)*(BASE##L) -PRECL \
|| EXP##l(5.0L) > (BASE##L)*(BASE##L)*(BASE##L)*(BASE##L)*(BASE##L) +PRECL) \
link_failure_##EXP##_INT()
EXP_INT(exp, M_E);
EXP_INT(exp2, 2.0);
EXP_INT(exp10, 10.0);
EXP_INT(pow10, 10.0);
#define EXPLOG_SAME(EXP, LOG) \
extern void link_failure_##EXP##_##LOG##_same(void); \
if (EXP(LOG(d1)) != d1 || EXP##f(LOG##f(f1)) != f1 \
|| EXP##l(LOG##l(ld1)) != ld1) link_failure_##EXP##_##LOG##_same()
EXPLOG_SAME(exp, log);
EXPLOG_SAME(exp2, log2);
EXPLOG_SAME(exp10, log10);
EXPLOG_SAME(pow10, log10);
#define EXPXEXP(EXP) \
extern void link_failure_##EXP##X##EXP(void); \
if (EXP(d1)*EXP(d2) != EXP(d1+d2) || EXP##f(f1)*EXP##f(f2) != EXP##f(f1+f2) \
|| EXP##l(ld1)*EXP##l(ld2) != EXP##l(ld1+ld2)) link_failure_##EXP##X##EXP()
EXPXEXP(exp);
EXPXEXP(exp2);
EXPXEXP(exp10);
EXPXEXP(pow10);
#define DIVEXP(EXP) \
extern void link_failure_div1_##EXP(void); \
if (d1/EXP(d2) != d1*EXP(-d2) || f1/EXP##f(f2) != f1*EXP##f(-f2) \
|| ld1/EXP##l(ld2) != ld1*EXP##l(-ld2)) link_failure_div1_##EXP(); \
extern void link_failure_div2_##EXP(void); \
if (EXP(d1)/EXP(d2) != EXP(d1-d2) || EXP##f(f1)/EXP##f(f2) != EXP##f(f1-f2) \
|| EXP##l(ld1)/EXP##l(ld2) != EXP##l(ld1-ld2)) link_failure_div2_##EXP()
DIVEXP(exp);
DIVEXP(exp2);
DIVEXP(exp10);
DIVEXP(pow10);
}
int main (void)
{
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment