This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]