Commit 02cf2861 by Alan Modra Committed by Alan Modra

PR70117, ppc long double isinf

gcc/
	PR target/70117
	* builtins.c (fold_builtin_classify): For IBM extended precision,
	look at just the high-order double to test for NaN.
	(fold_builtin_interclass_mathfn): Similarly for Inf.  For isnormal
	test just the high double for Inf but both doubles for subnormal
	limit.
gcc/testsuite/
	* gcc.target/powerpc/pr70117.c: New.

From-SVN: r234821
parent 1f395579
2016-04-08 Alan Modra <amodra@gmail.com>
PR target/70117
* builtins.c (fold_builtin_classify): For IBM extended precision,
look at just the high-order double to test for NaN.
(fold_builtin_interclass_mathfn): Similarly for Inf. For isnormal
test just the high double for Inf but both doubles for subnormal
limit.
2016-04-07 Jakub Jelinek <jakub@redhat.com>
* cgraph.h (struct cgraph_simd_clone): Add mask_mode field.
......
......@@ -7529,6 +7529,8 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
mode = TYPE_MODE (TREE_TYPE (arg));
bool is_ibm_extended = MODE_COMPOSITE_P (mode);
/* If there is no optab, try generic code. */
switch (DECL_FUNCTION_CODE (fndecl))
{
......@@ -7538,10 +7540,18 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
{
/* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
tree const type = TREE_TYPE (arg);
tree type = TREE_TYPE (arg);
REAL_VALUE_TYPE r;
char buf[128];
if (is_ibm_extended)
{
/* NaN and Inf are encoded in the high-order double value
only. The low-order value is not significant. */
type = double_type_node;
mode = DFmode;
arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
}
get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
real_from_string (&r, buf);
result = build_call_expr (isgr_fn, 2,
......@@ -7554,10 +7564,18 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
{
/* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
tree const type = TREE_TYPE (arg);
tree type = TREE_TYPE (arg);
REAL_VALUE_TYPE r;
char buf[128];
if (is_ibm_extended)
{
/* NaN and Inf are encoded in the high-order double value
only. The low-order value is not significant. */
type = double_type_node;
mode = DFmode;
arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
}
get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
real_from_string (&r, buf);
result = build_call_expr (isle_fn, 2,
......@@ -7577,21 +7595,72 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
/* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
islessequal(fabs(x),DBL_MAX). */
tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
tree const type = TREE_TYPE (arg);
tree type = TREE_TYPE (arg);
tree orig_arg, max_exp, min_exp;
machine_mode orig_mode = mode;
REAL_VALUE_TYPE rmax, rmin;
char buf[128];
orig_arg = arg = builtin_save_expr (arg);
if (is_ibm_extended)
{
/* Use double to test the normal range of IBM extended
precision. Emin for IBM extended precision is
different to emin for IEEE double, being 53 higher
since the low double exponent is at least 53 lower
than the high double exponent. */
type = double_type_node;
mode = DFmode;
arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
}
arg = fold_build1_loc (loc, ABS_EXPR, type, arg);
get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
real_from_string (&rmax, buf);
sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
real_from_string (&rmin, buf);
arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
result = build_call_expr (isle_fn, 2, arg,
build_real (type, rmax));
result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
build_call_expr (isge_fn, 2, arg,
build_real (type, rmin)));
max_exp = build_real (type, rmax);
min_exp = build_real (type, rmin);
max_exp = build_call_expr (isle_fn, 2, arg, max_exp);
if (is_ibm_extended)
{
/* Testing the high end of the range is done just using
the high double, using the same test as isfinite().
For the subnormal end of the range we first test the
high double, then if its magnitude is equal to the
limit of 0x1p-969, we test whether the low double is
non-zero and opposite sign to the high double. */
tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS);
tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp);
tree eq_min = fold_build2 (EQ_EXPR, integer_type_node,
arg, min_exp);
tree as_complex = build1 (VIEW_CONVERT_EXPR,
complex_double_type_node, orig_arg);
tree hi_dbl = build1 (REALPART_EXPR, type, as_complex);
tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex);
tree zero = build_real (type, dconst0);
tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero);
tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero);
tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero);
tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node,
fold_build3 (COND_EXPR,
integer_type_node,
hilt, logt, lolt));
eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node,
eq_min, ok_lo);
min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node,
gt_min, eq_min);
}
else
{
tree const isge_fn
= builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
min_exp = build_call_expr (isge_fn, 2, arg, min_exp);
}
result = fold_build2 (BIT_AND_EXPR, integer_type_node,
max_exp, min_exp);
return result;
}
default:
......@@ -7664,6 +7733,15 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
if (!HONOR_NANS (arg))
return omit_one_operand_loc (loc, type, integer_zero_node, arg);
{
bool is_ibm_extended = MODE_COMPOSITE_P (TYPE_MODE (TREE_TYPE (arg)));
if (is_ibm_extended)
{
/* NaN and Inf are encoded in the high-order double value
only. The low-order value is not significant. */
arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg);
}
}
arg = builtin_save_expr (arg);
return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
......
2016-04-08 Alan Modra <amodra@gmail.com>
* gcc.target/powerpc/pr70117.c: New.
2016-04-07 Jakub Jelinek <jakub@redhat.com>
PR testsuite/70581
......
/* { dg-do run { target { powerpc*-*-linux* powerpc*-*-darwin* powerpc*-*-aix* rs6000-*-* } } } */
/* { dg-options "-std=c99 -mlong-double-128 -O2" } */
#include <float.h>
union gl_long_double_union
{
struct { double hi; double lo; } dd;
long double ld;
};
/* This is gnulib's LDBL_MAX which, being 107 bits in precision, is
slightly larger than gcc's 106 bit precision LDBL_MAX. */
volatile union gl_long_double_union gl_LDBL_MAX =
{ { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL } };
volatile double min_denorm = 0x1p-1074;
volatile double ld_low = 0x1p-969;
volatile double dinf = 1.0/0.0;
volatile double dnan = 0.0/0.0;
int
main (void)
{
long double ld;
ld = gl_LDBL_MAX.ld;
if (__builtin_isinfl (ld))
__builtin_abort ();
ld = -gl_LDBL_MAX.ld;
if (__builtin_isinfl (ld))
__builtin_abort ();
ld = gl_LDBL_MAX.ld;
if (!__builtin_isfinite (ld))
__builtin_abort ();
ld = -gl_LDBL_MAX.ld;
if (!__builtin_isfinite (ld))
__builtin_abort ();
ld = ld_low;
if (!__builtin_isnormal (ld))
__builtin_abort ();
ld = -ld_low;
if (!__builtin_isnormal (ld))
__builtin_abort ();
ld = -min_denorm;
ld += ld_low;
if (__builtin_isnormal (ld))
__builtin_abort ();
ld = min_denorm;
ld -= ld_low;
if (__builtin_isnormal (ld))
__builtin_abort ();
ld = 0.0;
if (__builtin_isnormal (ld))
__builtin_abort ();
ld = -0.0;
if (__builtin_isnormal (ld))
__builtin_abort ();
ld = LDBL_MAX;
if (!__builtin_isnormal (ld))
__builtin_abort ();
ld = -LDBL_MAX;
if (!__builtin_isnormal (ld))
__builtin_abort ();
ld = gl_LDBL_MAX.ld;
if (!__builtin_isnormal (ld))
__builtin_abort ();
ld = -gl_LDBL_MAX.ld;
if (!__builtin_isnormal (ld))
__builtin_abort ();
ld = dinf;
if (__builtin_isnormal (ld))
__builtin_abort ();
ld = -dinf;
if (__builtin_isnormal (ld))
__builtin_abort ();
ld = dnan;
if (__builtin_isnormal (ld))
__builtin_abort ();
ld = -dnan;
if (__builtin_isnormal (ld))
__builtin_abort ();
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