Commit 7a2a25ab by Kaveh R. Ghazi Committed by Kaveh Ghazi

builtins.c (fold_builtin_frexp): New.

	* builtins.c (fold_builtin_frexp): New.
	(fold_builtin_2): Use it.

testsuite:
	* gcc.dg/torture/builtin-frexp-1.c: New test.

From-SVN: r122249
parent 03d12b64
2007-02-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (fold_builtin_frexp): New.
(fold_builtin_2): Use it.
2007-02-22 Mark Mitchell <mark@codesourcery.com>
* doc/invoke.texi (Spec Files): Document getenv spec function.
......
......@@ -9017,6 +9017,62 @@ fold_builtin_carg (tree arg, tree type)
return NULL_TREE;
}
/* Fold a call to builtin frexp, we can assume the base is 2. */
static tree
fold_builtin_frexp (tree arg0, tree arg1, tree rettype)
{
if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
return NULL_TREE;
STRIP_NOPS (arg0);
if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
return NULL_TREE;
arg1 = build_fold_indirect_ref (arg1);
/* Proceed if a valid pointer type was passed in. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node)
{
const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
tree frac, exp;
switch (value->cl)
{
case rvc_zero:
/* For +-0, return (*exp = 0, +-0). */
exp = integer_zero_node;
frac = arg0;
break;
case rvc_nan:
case rvc_inf:
/* For +-NaN or +-Inf, *exp is unspecified, return arg0. */
return omit_one_operand (rettype, arg0, arg1);
case rvc_normal:
{
/* Since the frexp function always expects base 2, and in
GCC normalized significands are already in the range
[0.5, 1.0), we have exactly what frexp wants. */
REAL_VALUE_TYPE frac_rvt = *value;
SET_REAL_EXP (&frac_rvt, 0);
frac = build_real (rettype, frac_rvt);
exp = build_int_cst (NULL_TREE, REAL_EXP (value));
}
break;
default:
gcc_unreachable ();
}
/* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1, exp);
TREE_SIDE_EFFECTS (arg1) = 1;
return fold_build2 (COMPOUND_EXPR, rettype, arg1, frac);
}
return NULL_TREE;
}
/* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true
then we can assume the base is two. If it's false, then we have to
check the mode of the TYPE parameter in certain cases. */
......@@ -9544,6 +9600,9 @@ fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
CASE_FLT_FN (BUILT_IN_SCALBLN):
return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/false);
CASE_FLT_FN (BUILT_IN_FREXP):
return fold_builtin_frexp (arg0, arg1, type);
case BUILT_IN_BZERO:
return fold_builtin_bzero (arg0, arg1, ignore);
......
2007-02-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/torture/builtin-frexp-1.c: New test.
2007-02-22 Mark Mitchell <mark@codesourcery.com>
* g++.dg/opt/switch4.C: Pass -fshort-enums -w.
/* Copyright (C) 2007 Free Software Foundation.
Verify that built-in folding of frexp is correctly performed by the
compiler.
Origin: Kaveh R. Ghazi, February 21, 2007. */
/* { dg-do link } */
extern void link_error(int);
/* Return TRUE if the sign of X != sign of Y. This is important when
comparing signed zeros. */
#define CKSGN_F(X,Y) \
(__builtin_copysignf(1.0F,(X)) != __builtin_copysignf(1.0F,(Y)))
#define CKSGN(X,Y) \
(__builtin_copysign(1.0,(X)) != __builtin_copysign(1.0,(Y)))
#define CKSGN_L(X,Y) \
(__builtin_copysignl(1.0L,(X)) != __builtin_copysignl(1.0L,(Y)))
/* We can only check the exponent when optimizing since we rely on
other optimizations to propagate the value. TRUE means an error
occurred. */
#ifdef __OPTIMIZE__
#define CKEXP(X,Y) X != Y
#else
#define CKEXP(X,Y) 0
#endif
/* Test that frexp(ARG,&i) == RES && i == EXP. Check the sign in
case we get -0.0. */
#define TESTIT_FREXP(ARG,RES,EXP) do { \
int i = 123456; \
if (__builtin_frexpf(ARG##f,&i) != RES##f \
|| CKEXP(i,EXP) \
|| CKSGN_F(__builtin_frexpf(ARG##f,&i),RES##f)) \
link_error(__LINE__); \
i = 123456; \
if (__builtin_frexp(ARG,&i) != RES \
|| CKEXP(i,EXP) \
|| CKSGN(__builtin_frexp(ARG,&i),RES)) \
link_error(__LINE__); \
i = 123456; \
if (__builtin_frexpl(ARG##l,&i) != RES##l \
|| CKEXP(i,EXP) \
|| CKSGN_L(__builtin_frexpl(ARG##l,&i),RES##l)) \
link_error(__LINE__); \
} while (0)
/* Test that FUNCRES(frexp(NEG FUNCARG(ARGARG),&i)) is false. Check
the sign as well. Ensure side-effects are evaluated in i. */
#define TESTIT_FREXP2(NEG,FUNCARG,ARGARG,FUNCRES) do { \
int i=5; \
if (!__builtin_##FUNCRES##f(__builtin_frexpf(NEG __builtin_##FUNCARG##f(ARGARG),&i)) \
|| CKSGN_F(__builtin_frexpf(NEG __builtin_##FUNCARG##f(ARGARG),(i++,&i)), NEG __builtin_##FUNCARG##f(ARGARG)) \
|| CKEXP(i,6)) \
link_error(__LINE__); \
if (!__builtin_##FUNCRES(__builtin_frexp(NEG __builtin_##FUNCARG(ARGARG),&i)) \
|| CKSGN(__builtin_frexp(NEG __builtin_##FUNCARG(ARGARG),(i++,&i)), NEG __builtin_##FUNCARG(ARGARG)) \
|| CKEXP(i,7)) \
link_error(__LINE__); \
if (!__builtin_##FUNCRES##l(__builtin_frexpl(NEG __builtin_##FUNCARG##l(ARGARG),&i)) \
|| CKSGN_L(__builtin_frexpl(NEG __builtin_##FUNCARG##l(ARGARG),(i++,&i)), NEG __builtin_##FUNCARG##l(ARGARG)) \
|| CKEXP(i,8)) \
link_error(__LINE__); \
} while (0)
void __attribute__ ((__noinline__))
foo(void)
{
/* Test that frexp(ARG1,&i) -> ARG2 && i == ARG3. */
TESTIT_FREXP (-0x1p40, -0.5, 41);
TESTIT_FREXP (-0x1p30, -0.5, 31);
TESTIT_FREXP (-0x1p20, -0.5, 21);
TESTIT_FREXP (-0x1p10, -0.5, 11);
TESTIT_FREXP (-0x1p5, -0.5, 6);
TESTIT_FREXP (-100/3.0, -100/192.0, 6);
TESTIT_FREXP (-1.5, -0.75, 1);
TESTIT_FREXP (-1.0, -0.5, 1);
TESTIT_FREXP (-1/3.0, -2/3.0, -1);
TESTIT_FREXP (-1/9.0, -8/9.0, -3);
TESTIT_FREXP (-0x1p-5, -0.5, -4);
TESTIT_FREXP (-0x1p-10, -0.5, -9);
TESTIT_FREXP (-0x1p-20, -0.5, -19);
TESTIT_FREXP (-0x1p-30, -0.5, -29);
TESTIT_FREXP (-0x1p-40, -0.5, -39);
TESTIT_FREXP (-0.0, -0.0, 0);
TESTIT_FREXP (0.0, 0.0, 0);
TESTIT_FREXP (0x1p-40, 0.5, -39);
TESTIT_FREXP (0x1p-30, 0.5, -29);
TESTIT_FREXP (0x1p-20, 0.5, -19);
TESTIT_FREXP (0x1p-10, 0.5, -9);
TESTIT_FREXP (0x1p-5, 0.5, -4);
TESTIT_FREXP (1/9.0, 8/9.0, -3);
TESTIT_FREXP (1/3.0, 2/3.0, -1);
TESTIT_FREXP (1.0, 0.5, 1);
TESTIT_FREXP (1.5, 0.75, 1);
TESTIT_FREXP (100/3.0, 100/192.0, 6);
TESTIT_FREXP (0x1p5, 0.5, 6);
TESTIT_FREXP (0x1p10, 0.5, 11);
TESTIT_FREXP (0x1p20, 0.5, 21);
TESTIT_FREXP (0x1p30, 0.5, 31);
TESTIT_FREXP (0x1p40, 0.5, 41);
/* Test for frexp(+-Inf,&i) -> +-Inf and frexp(+-NaN,&i) -> +-NaN.
Exponent is left unspecified, but we test for side-effects. */
TESTIT_FREXP2 ( ,inf, , isinf);
TESTIT_FREXP2 (- ,inf, , isinf);
TESTIT_FREXP2 ( ,nan, "", isnan);
TESTIT_FREXP2 (- ,nan, "", isnan);
}
int main()
{
foo ();
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