From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18468 invoked by alias); 19 May 2007 04:23:26 -0000 Received: (qmail 18457 invoked by uid 22791); 19 May 2007 04:23:24 -0000 X-Spam-Check-By: sourceware.org Received: from caip.rutgers.edu (HELO caip.rutgers.edu) (128.6.236.16) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 19 May 2007 04:23:20 +0000 Received: from caipclassic.rutgers.edu (caipclassic.rutgers.edu [128.6.237.54]) by caip.rutgers.edu (8.13.8/8.13.5) with ESMTP id l4J4N97i025525 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sat, 19 May 2007 00:23:09 -0400 Date: Sat, 19 May 2007 04:23:00 -0000 From: "Kaveh R. GHAZI" To: Richard Guenther cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH]: PR middle-end/30250, use MPFR for lgamma_r/gamma_r In-Reply-To: <84fc9c000705170315g15b30422ga7884f0779c17003@mail.gmail.com> Message-ID: References: <84fc9c000705170315g15b30422ga7884f0779c17003@mail.gmail.com> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-05/txt/msg01269.txt.bz2 On Thu, 17 May 2007, Richard Guenther wrote: > > + /* Dereference the arg_sg pointer argument. */ > > + arg_sg = build_fold_indirect_ref (arg_sg); > > + /* Proceed iff a valid pointer type was passed in. */ > > + if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_sg)) == integer_type_node) > > This check should be done earlier based on the pointed to type of the > argument. Ok with this change. Done. I installed the revised patch below. Thanks again for your reviews. Regards, --Kaveh 2007-05-07 Kaveh R. Ghazi PR middle-end/30250 * builtins.c (do_mpfr_lgamma_r): New. (fold_builtin_2): Handle builtin gamma_r/lgamma_r. * tree.h (CASE_FLT_FN_REENT): New. testsuite: * gcc.dg/torture/builtin-math-2.c: Add gamma_r/lgamma_r tests. * gcc.dg/torture/builtin-math-4.c: Likewise. diff -rup orig/egcc-SVN20070517/gcc/builtins.c egcc-SVN20070517/gcc/builtins.c --- orig/egcc-SVN20070517/gcc/builtins.c 2007-05-17 23:03:48.000000000 -0400 +++ egcc-SVN20070517/gcc/builtins.c 2007-05-18 01:05:54.447296033 -0400 @@ -236,6 +236,7 @@ static tree do_mpfr_bessel_n (tree, tree int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t), const REAL_VALUE_TYPE *, bool); static tree do_mpfr_remquo (tree, tree, tree); +static tree do_mpfr_lgamma_r (tree, tree, tree); #endif /* Return true if NODE should be considered for inline expansion regardless @@ -9935,6 +9936,13 @@ fold_builtin_2 (tree fndecl, tree arg0, && validate_arg(arg1, REAL_TYPE)) return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder); break; + + CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */ + CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */ + if (validate_arg (arg0, REAL_TYPE) + && validate_arg(arg1, POINTER_TYPE)) + return do_mpfr_lgamma_r (arg0, arg1, type); + break; #endif CASE_FLT_FN (BUILT_IN_ATAN2): @@ -12692,4 +12700,67 @@ do_mpfr_remquo (tree arg0, tree arg1, tr } return result; } + +/* If ARG is a REAL_CST, call mpfr_lgamma() on it and return the + resulting value as a tree with type TYPE. The mpfr precision is + set to the precision of TYPE. We assume that this mpfr function + returns zero if the result could be calculated exactly within the + requested precision. In addition, the integer pointer represented + by ARG_SG will be dereferenced and set to the appropriate signgam + (-1,1) value. */ + +static tree +do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type) +{ + tree result = NULL_TREE; + + STRIP_NOPS (arg); + + /* To proceed, MPFR must exactly represent the target floating point + format, which only happens when the target base equals two. Also + verify ARG is a constant and that ARG_SG is an int pointer. */ + if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 + && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg) + && TREE_CODE (TREE_TYPE (arg_sg)) == POINTER_TYPE + && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg_sg))) == integer_type_node) + { + const REAL_VALUE_TYPE *const ra = TREE_REAL_CST_PTR (arg); + + /* In addition to NaN and Inf, the argument cannot be zero or a + negative integer. */ + if (!real_isnan (ra) && !real_isinf (ra) + && ra->cl != rvc_zero + && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type)))) + { + const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p; + int inexact, sg; + mpfr_t m; + tree result_lg; + + mpfr_init2 (m, prec); + mpfr_from_real (m, ra, GMP_RNDN); + mpfr_clear_flags (); + inexact = mpfr_lgamma (m, &sg, m, GMP_RNDN); + result_lg = do_mpfr_ckconv (m, type, inexact); + mpfr_clear (m); + if (result_lg) + { + tree result_sg; + + /* Dereference the arg_sg pointer argument. */ + arg_sg = build_fold_indirect_ref (arg_sg); + /* Assign the signgam value into *arg_sg. */ + result_sg = fold_build2 (MODIFY_EXPR, + TREE_TYPE (arg_sg), arg_sg, + build_int_cst (NULL, sg)); + TREE_SIDE_EFFECTS (result_sg) = 1; + /* Combine the signgam assignment with the lgamma result. */ + result = non_lvalue (fold_build2 (COMPOUND_EXPR, type, + result_sg, result_lg)); + } + } + } + + return result; +} #endif diff -rup orig/egcc-SVN20070517/gcc/tree.h egcc-SVN20070517/gcc/tree.h --- orig/egcc-SVN20070517/gcc/tree.h 2007-05-03 03:14:35.000000000 -0400 +++ egcc-SVN20070517/gcc/tree.h 2007-05-18 00:27:19.050082272 -0400 @@ -273,6 +273,7 @@ extern const char * built_in_names[(int) #define BUILTIN_ROOT_P(FN) (BUILTIN_SQRT_P (FN) || BUILTIN_CBRT_P (FN)) #define CASE_FLT_FN(FN) case FN: case FN##F: case FN##L +#define CASE_FLT_FN_REENT(FN) case FN##_R: case FN##F_R: case FN##L_R #define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL /* An array of _DECL trees for the above. */ diff -rup orig/egcc-SVN20070517/gcc/testsuite/gcc.dg/torture/builtin-math-2.c egcc-SVN20070517/gcc/testsuite/gcc.dg/torture/builtin-math-2.c --- orig/egcc-SVN20070517/gcc/testsuite/gcc.dg/torture/builtin-math-2.c 2007-05-17 23:03:22.000000000 -0400 +++ egcc-SVN20070517/gcc/testsuite/gcc.dg/torture/builtin-math-2.c 2007-05-18 00:27:19.051938461 -0400 @@ -49,6 +49,13 @@ extern void fool (long double); fool (__builtin_remquol (ARG1##L, ARG2##L, &quo)); \ } while (0) +#define TESTIT_REENT(FUNC,ARG1) do { \ + int sg; \ + foof (__builtin_##FUNC##f_r (ARG1##F, &sg)); \ + foo (__builtin_##FUNC##_r (ARG1, &sg)); \ + fool (__builtin_##FUNC##l_r (ARG1##L, &sg)); \ +} while (0) + void bar() { /* An argument of NaN is not evaluated at compile-time. */ @@ -266,6 +273,21 @@ void bar() TESTIT2 (remainder, 1.0, -0.0); TESTIT2 (drem, 1.0, 0.0); TESTIT2 (drem, 1.0, -0.0); + + /* The argument to lgamma* cannot be zero or a negative integer. */ + TESTIT_REENT (lgamma, -4.0); /* lgamma_r */ + TESTIT_REENT (lgamma, -3.0); /* lgamma_r */ + TESTIT_REENT (lgamma, -2.0); /* lgamma_r */ + TESTIT_REENT (lgamma, -1.0); /* lgamma_r */ + TESTIT_REENT (lgamma, -0.0); /* lgamma_r */ + TESTIT_REENT (lgamma, 0.0); /* lgamma_r */ + + TESTIT_REENT (gamma, -4.0); /* gamma_r */ + TESTIT_REENT (gamma, -3.0); /* gamma_r */ + TESTIT_REENT (gamma, -2.0); /* gamma_r */ + TESTIT_REENT (gamma, -1.0); /* gamma_r */ + TESTIT_REENT (gamma, -0.0); /* gamma_r */ + TESTIT_REENT (gamma, 0.0); /* gamma_r */ } /* { dg-final { scan-tree-dump-times "exp2 " 9 "original" } } */ @@ -340,4 +362,10 @@ void bar() /* { dg-final { scan-tree-dump-times "drem " 2 "original" } } */ /* { dg-final { scan-tree-dump-times "dremf" 2 "original" } } */ /* { dg-final { scan-tree-dump-times "dreml" 2 "original" } } */ +/* { dg-final { scan-tree-dump-times "lgamma_r " 6 "original" } } */ +/* { dg-final { scan-tree-dump-times "lgammaf_r" 6 "original" } } */ +/* { dg-final { scan-tree-dump-times "lgammal_r" 6 "original" } } */ +/* { dg-final { scan-tree-dump-times "_gamma_r " 6 "original" } } */ +/* { dg-final { scan-tree-dump-times "_gammaf_r" 6 "original" } } */ +/* { dg-final { scan-tree-dump-times "_gammal_r" 6 "original" } } */ /* { dg-final { cleanup-tree-dump "original" } } */ diff -rup orig/egcc-SVN20070517/gcc/testsuite/gcc.dg/torture/builtin-math-4.c egcc-SVN20070517/gcc/testsuite/gcc.dg/torture/builtin-math-4.c --- orig/egcc-SVN20070517/gcc/testsuite/gcc.dg/torture/builtin-math-4.c 2007-05-17 23:03:22.000000000 -0400 +++ egcc-SVN20070517/gcc/testsuite/gcc.dg/torture/builtin-math-4.c 2007-05-18 00:27:19.053318162 -0400 @@ -103,6 +103,44 @@ extern void link_error(int); link_error(__LINE__); \ } while (0) +/* Test that FUNC(ARG,&SG) == (RES) && SG == RES_SG. */ +#define TESTIT_LGAMMA_REENT(FUNC,ARG,RES,RES_SG) do { \ + int sg; \ + sg = 123; \ + if (__builtin_##FUNC##f_r(ARG##F,&sg) != RES##F \ + || sg != RES_SG \ + || CKSGN_F(__builtin_##FUNC##f_r(ARG##F,&sg),RES##F)) \ + link_error(__LINE__); \ + sg = 123; \ + if (__builtin_##FUNC##_r(ARG,&sg) != RES \ + || sg != RES_SG \ + || CKSGN(__builtin_##FUNC##_r(ARG,&sg),RES)) \ + link_error(__LINE__); \ + sg = 123; \ + if (__builtin_##FUNC##l_r(ARG##L,&sg) != RES##L \ + || sg != RES_SG \ + || CKSGN_L(__builtin_##FUNC##l_r(ARG##L,&sg),RES##L)) \ + link_error(__LINE__); \ + } while (0) + +/* Range test, check that (LOW) < FUNC(ARG,&SG) < (HI), and also test + that SG == RES_SG. */ +#define TESTIT_LGAMMA_REENT_R(FUNC,ARG,LOW,HI,RES_SG) do { \ + int sg; \ + sg = 123; \ + if (__builtin_##FUNC##f_r(ARG,&sg) <= (LOW) || __builtin_##FUNC##f_r(ARG,&sg) >= (HI) \ + || sg != RES_SG) \ + link_error(__LINE__); \ + sg = 123; \ + if (__builtin_##FUNC##_r(ARG,&sg) <= (LOW) || __builtin_##FUNC##_r(ARG,&sg) >= (HI) \ + || sg != RES_SG) \ + link_error(__LINE__); \ + sg = 123; \ + if (__builtin_##FUNC##l_r(ARG,&sg) <= (LOW) || __builtin_##FUNC##l_r(ARG,&sg) >= (HI) \ + || sg != RES_SG) \ + link_error(__LINE__); \ + } while (0) + int main (void) { #ifdef __OPTIMIZE__ @@ -249,7 +287,27 @@ int main (void) MAXIT(remquol, -(__INT_MAX__+1.0L), 0); MAXIT(remquol, -(__INT_MAX__+2.0L), -1); } -#endif + /* These tests rely on propagating the variable sg which contains + signgam. This happens only when optimization is turned on. */ + TESTIT_LGAMMA_REENT_R (lgamma, -2.5, -0.06, -0.05, -1); /* lgamma_r(-2.5) == -0.056... */ + TESTIT_LGAMMA_REENT_R (lgamma, -1.5, 0.86, 0.87, 1); /* lgamma_r(-1.5) == 0.860... */ + TESTIT_LGAMMA_REENT_R (lgamma, -0.5, 1.26, 1.27, -1); /* lgamma_r(-0.5) == 1.265... */ + TESTIT_LGAMMA_REENT_R (lgamma, 0.5, 0.57, 0.58, 1); /* lgamma_r(0.5) == 0.572... */ + TESTIT_LGAMMA_REENT (lgamma, 1.0, 0.0, 1); /* lgamma_r(1) == 0 */ + TESTIT_LGAMMA_REENT_R (lgamma, 1.5, -0.13, -0.12, 1); /* lgamma_r(1.5) == -0.120... */ + TESTIT_LGAMMA_REENT (lgamma, 2.0, 0.0, 1); /* lgamma_r(2) == 0 */ + TESTIT_LGAMMA_REENT_R (lgamma, 2.5, 0.28, 0.29, 1); /* lgamma_r(2.5) == 0.284... */ + + TESTIT_LGAMMA_REENT_R (gamma, -2.5, -0.06, -0.05, -1); /* gamma_r(-2.5) == -0.056... */ + TESTIT_LGAMMA_REENT_R (gamma, -1.5, 0.86, 0.87, 1); /* gamma_r(-1.5) == 0.860... */ + TESTIT_LGAMMA_REENT_R (gamma, -0.5, 1.26, 1.27, -1); /* gamma_r(-0.5) == 1.265... */ + TESTIT_LGAMMA_REENT_R (gamma, 0.5, 0.57, 0.58, 1); /* gamma_r(0.5) == 0.572... */ + TESTIT_LGAMMA_REENT (gamma, 1.0, 0.0, 1); /* gamma_r(1) == 0 */ + TESTIT_LGAMMA_REENT_R (gamma, 1.5, -0.13, -0.12, 1); /* gamma_r(1.5) == -0.120... */ + TESTIT_LGAMMA_REENT (gamma, 2.0, 0.0, 1); /* gamma_r(2) == 0 */ + TESTIT_LGAMMA_REENT_R (gamma, 2.5, 0.28, 0.29, 1); /* gamma_r(2.5) == 0.284... */ +#endif + return 0; }