This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Move folding of round -> lround from convert.c to fold_unary
On Mon, 12 Dec 2005, Richard Henderson wrote:
> On Wed, Dec 07, 2005 at 01:47:10PM +0100, Richard Guenther wrote:
> > + /* Convert e.g. (long)round(d) -> lround(d). */
> > + /* If we're converting to char, we may encounter differing behavior
> > + between converting from double->char vs double->long->char.
> > + We're in "undefined" territory but we prefer to be conservative,
> > + so only proceed in "unsafe" math mode. */
> > + if (optimize
> > + && TREE_CODE (op0) == CALL_EXPR
> > + && TREE_CODE (type) == INTEGER_TYPE
> > + && (flag_unsafe_math_optimizations
> > + || (long_integer_type_node
> > + && (TYPE_PRECISION (type)
> > + >= TYPE_PRECISION (long_integer_type_node)))))
>
> Um, shouldn't type have *less* precision than long?
>
> Suppose long is 32 bits. Suppose type is 64 bits. When
> converting 1p62, we don't want the value truncated. The
> code appears to try to handle this,
>
> > + bool ll = (TYPE_MAIN_VARIANT (type)
> > + == TYPE_MAIN_VARIANT (long_long_integer_type_node));
>
> but will fail for types larger than long long (e.g. TImode),
> and for certain kinds of bitfields:
>
> struct {
> long long x : 52;
> } s;
> s.x = round(d);
>
> Finally, long_integer_type_node only makes sense for C/C++.
> It is in fact definitely wrong for Java. We probably ought to
> clarify this by creating c_long_integer_type_node and friends,
> and also moving the C builtins someplace generic; in general
> all languages are liking to take advantage of the C runtime.
So, more like
2005-12-12 Richard Guenther <rguenther@suse.de>
* convert.c (convert_to_integer): Move folding of
rounding functions ...
* fold-const.c (fold_unary): ... here.
Index: convert.c
===================================================================
*** convert.c (revision 108153)
--- convert.c (working copy)
*************** convert_to_integer (tree type, tree expr
*** 334,413 ****
return error_mark_node;
}
- /* Convert e.g. (long)round(d) -> lround(d). */
- /* If we're converting to char, we may encounter differing behavior
- between converting from double->char vs double->long->char.
- We're in "undefined" territory but we prefer to be conservative,
- so only proceed in "unsafe" math mode. */
- if (optimize
- && (flag_unsafe_math_optimizations
- || (long_integer_type_node
- && outprec >= TYPE_PRECISION (long_integer_type_node))))
- {
- tree s_expr = strip_float_extensions (expr);
- tree s_intype = TREE_TYPE (s_expr);
- const enum built_in_function fcode = builtin_mathfn_code (s_expr);
- tree fn = 0;
-
- switch (fcode)
- {
- CASE_FLT_FN (BUILT_IN_CEIL):
- /* Only convert in ISO C99 mode. */
- if (!TARGET_C99_FUNCTIONS)
- break;
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node))
- fn = mathfn_built_in (s_intype, BUILT_IN_LLCEIL);
- else
- fn = mathfn_built_in (s_intype, BUILT_IN_LCEIL);
- break;
-
- CASE_FLT_FN (BUILT_IN_FLOOR):
- /* Only convert in ISO C99 mode. */
- if (!TARGET_C99_FUNCTIONS)
- break;
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node))
- fn = mathfn_built_in (s_intype, BUILT_IN_LLFLOOR);
- else
- fn = mathfn_built_in (s_intype, BUILT_IN_LFLOOR);
- break;
-
- CASE_FLT_FN (BUILT_IN_ROUND):
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node))
- fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND);
- else
- fn = mathfn_built_in (s_intype, BUILT_IN_LROUND);
- break;
-
- CASE_FLT_FN (BUILT_IN_RINT):
- /* Only convert rint* if we can ignore math exceptions. */
- if (flag_trapping_math)
- break;
- /* ... Fall through ... */
- CASE_FLT_FN (BUILT_IN_NEARBYINT):
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node))
- fn = mathfn_built_in (s_intype, BUILT_IN_LLRINT);
- else
- fn = mathfn_built_in (s_intype, BUILT_IN_LRINT);
- break;
-
- CASE_FLT_FN (BUILT_IN_TRUNC):
- {
- tree arglist = TREE_OPERAND (s_expr, 1);
- return convert_to_integer (type, TREE_VALUE (arglist));
- }
-
- default:
- break;
- }
-
- if (fn)
- {
- tree arglist = TREE_OPERAND (s_expr, 1);
- tree newexpr = build_function_call_expr (fn, arglist);
- return convert_to_integer (type, newexpr);
- }
- }
-
switch (TREE_CODE (intype))
{
case POINTER_TYPE:
--- 334,339 ----
Index: fold-const.c
===================================================================
*** fold-const.c (revision 108411)
--- fold-const.c (working copy)
*************** fold_unary (enum tree_code code, tree ty
*** 7009,7014 ****
--- 7009,7078 ----
TREE_OPERAND (arg0, 1));
}
+ /* Convert e.g. (long)round(d) -> lround(d). */
+ if (optimize
+ && TREE_CODE (op0) == CALL_EXPR
+ && TREE_CODE (type) == INTEGER_TYPE
+ && long_long_integer_type_node
+ && TYPE_PRECISION (type)
+ <= TYPE_PRECISION (long_long_integer_type_node))
+ {
+ tree s_intype = TREE_TYPE (op0);
+ const enum built_in_function fcode = builtin_mathfn_code (op0);
+ tree fn = 0;
+ bool ll = (!long_integer_type_node
+ || (TYPE_PRECISION (type)
+ > TYPE_PRECISION (long_integer_type_node)));
+
+ switch (fcode)
+ {
+ CASE_FLT_FN (BUILT_IN_CEIL):
+ /* Only convert in ISO C99 mode. */
+ if (!TARGET_C99_FUNCTIONS)
+ break;
+ fn = mathfn_built_in (s_intype,
+ ll ? BUILT_IN_LLCEIL : BUILT_IN_LCEIL);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_FLOOR):
+ /* Only convert in ISO C99 mode. */
+ if (!TARGET_C99_FUNCTIONS)
+ break;
+ fn = mathfn_built_in (s_intype,
+ ll ? BUILT_IN_LLFLOOR : BUILT_IN_LFLOOR);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_ROUND):
+ fn = mathfn_built_in (s_intype,
+ ll ? BUILT_IN_LLROUND : BUILT_IN_LROUND);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_RINT):
+ /* Only convert rint* if we can ignore math exceptions. */
+ if (flag_trapping_math)
+ break;
+ /* ... Fall through ... */
+ CASE_FLT_FN (BUILT_IN_NEARBYINT):
+ fn = mathfn_built_in (s_intype,
+ ll ? BUILT_IN_LLRINT : BUILT_IN_LRINT);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_TRUNC):
+ return fold_build1 (FIX_TRUNC_EXPR, type,
+ TREE_VALUE (TREE_OPERAND (op0, 1)));
+
+ default:
+ break;
+ }
+
+ if (fn)
+ {
+ tree arglist = TREE_OPERAND (op0, 1);
+ tree newexpr = build_function_call_expr (fn, arglist);
+ return fold_convert (type, newexpr);
+ }
+ }
+
tem = fold_convert_const (code, type, arg0);
return tem ? tem : NULL_TREE;