From: "Kaveh R. GHAZI" <ghazi@caip.rutgers.edu>
To: Richard Guenther <richard.guenther@gmail.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH]: PR middle-end/30250, use MPFR for lgamma_r/gamma_r
Date: Sat, 19 May 2007 04:23:00 -0000 [thread overview]
Message-ID: <Pine.GSO.4.58.0705190020280.10677@caipclassic.rutgers.edu> (raw)
In-Reply-To: <84fc9c000705170315g15b30422ga7884f0779c17003@mail.gmail.com>
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 <ghazi@caip.rutgers.edu>
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;
}
next prev parent reply other threads:[~2007-05-19 4:23 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-07 16:04 Kaveh R. GHAZI
2007-05-17 10:15 ` Richard Guenther
2007-05-19 4:23 ` Kaveh R. GHAZI [this message]
2007-05-23 21:53 ` Richard Guenther
2007-05-23 22:57 ` Kaveh R. GHAZI
2007-05-24 8:15 ` Richard Guenther
2007-05-24 10:16 ` Richard Guenther
2007-05-24 16:59 ` Janis Johnson
2007-05-24 21:09 ` Kaveh R. GHAZI
2007-05-24 22:43 ` Janis Johnson
2007-05-24 16:46 ` Joe Buck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.GSO.4.58.0705190020280.10677@caipclassic.rutgers.edu \
--to=ghazi@caip.rutgers.edu \
--cc=gcc-patches@gcc.gnu.org \
--cc=richard.guenther@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).