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]

Simplify floating point conversions IV


> On Wed, Nov 06, 2002 at 10:48:03PM +0100, Jan Hubicka wrote:
> > +       /* Wind away possible cast.  */
> > +       if (TREE_CODE (arg0) == NOP_EXPR
> > + 	  && (TYPE_PRECISION (TREE_TYPE (arg0))
> > + 	      > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
> > + 	arg0 = TREE_OPERAND (arg0, 0);
> [...]
> > +       /* Be curefull about integer to fp conversions.
> > + 	 These may overflow still.  */
> > +       if (FLOAT_TYPE_P (TREE_TYPE (arg0))
> 
> I'd rather something like
> 
> static tree
> strip_float_extensions (exp)
>      tree exp;
> {
>   tree sub, expt, subt;
> 
>   if (TREE_CODE (exp) != NOP_EXPR)
>     return exp;
> 
>   sub = TREE_OPERAND (exp, 0);
>   subt = TREE_TYPE (sub);
>   expt = TREE_TYPE (exp);
> 
>   if (!FLOAT_TYPE_P (subt))
>     return exp;
> 
>   if (TYPE_PRECISION (subt) > TYPE_PRECISION (expt))
>     return exp;
> 
>   return strip_float_extensions (sub);
> }
> 
> > + 	case RDIV_EXPR:
> > + 	   {
> > + 	     tree arg0 = TREE_OPERAND (expr, 0);
> > + 	     tree arg1 = TREE_OPERAND (expr, 1);
> > + 
> > + 	     /* Unwind possible casts.  */
> 
> Useful here as well.
Nice.  I've added that and suppressed the builtin transformation
when not optimizing.

OK now?

Wed Nov  6 19:48:32 PST 2002  Jan Hubicka  <jh@suse.cz>
	* convert.c (strip_float_extensions): New function.
	(convert_to_real): Optimize some cases.
Index: convert.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/convert.c,v
retrieving revision 1.19
diff -c -3 -p -r1.19 convert.c
*** convert.c	4 Jul 2002 06:38:54 -0000	1.19
--- convert.c	7 Nov 2002 10:53:27 -0000
*************** Software Foundation, 59 Temple Place - S
*** 30,35 ****
--- 30,36 ----
  #include "convert.h"
  #include "toplev.h"
  #include "langhooks.h"
+ static tree strip_float_extensions PARAMS ((tree));
  
  /* Convert EXPR to some pointer or reference type TYPE.
  
*************** convert_to_pointer (type, expr)
*** 71,76 ****
--- 72,101 ----
      }
  }
  
+ /* Avoid any floating point extensions from EXP.  */
+ static tree
+ strip_float_extensions (exp)
+      tree exp;
+ {
+   tree sub, expt, subt;
+ 
+   if (TREE_CODE (exp) != NOP_EXPR)
+     return exp;
+ 
+   sub = TREE_OPERAND (exp, 0);
+   subt = TREE_TYPE (sub);
+   expt = TREE_TYPE (exp);
+ 
+   if (!FLOAT_TYPE_P (subt))
+     return exp;
+ 
+   if (TYPE_PRECISION (subt) > TYPE_PRECISION (expt))
+     return exp;
+ 
+   return strip_float_extensions (sub);
+ }
+ 
+ 
  /* Convert EXPR to some floating-point type TYPE.
  
     EXPR must be float, integer, or enumeral;
*************** tree
*** 80,85 ****
--- 105,244 ----
  convert_to_real (type, expr)
       tree type, expr;
  {
+   enum built_in_function fcode = builtin_mathfn_code (expr);
+   tree itype = TREE_TYPE (expr);
+ 
+   /* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */
+   if ((fcode == BUILT_IN_SQRT
+        || fcode == BUILT_IN_SQRTL
+        || fcode == BUILT_IN_SIN
+        || fcode == BUILT_IN_SINL
+        || fcode == BUILT_IN_COS
+        || fcode == BUILT_IN_COSL
+        || fcode == BUILT_IN_EXP
+        || fcode == BUILT_IN_EXPL)
+       && optimize
+       && (TYPE_MODE (type) == TYPE_MODE (double_type_node)
+           || TYPE_MODE (type) == TYPE_MODE (float_type_node)))
+     {
+       tree arg0 = strip_float_extensions (TREE_VALUE (TREE_OPERAND (expr, 1)));
+       tree newtype = type;
+ 
+       /* We have (outertype)sqrt((innertype)x).  Choose the wider mode from
+ 	 the both as the safe type for operation.  */
+       if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type))
+ 	newtype = TREE_TYPE (arg0);
+ 
+       /* Be curefull about integer to fp conversions.
+ 	 These may overflow still.  */
+       if (FLOAT_TYPE_P (TREE_TYPE (arg0))
+ 	  && TYPE_PRECISION (newtype) <= TYPE_PRECISION (itype)
+ 	  && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node)
+ 	      || TYPE_MODE (newtype) == TYPE_MODE (float_type_node)))
+ 	{
+ 	  tree arglist;
+ 	  if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
+ 	    switch (fcode)
+ 	      {
+ 	      case BUILT_IN_SQRT:
+ 	      case BUILT_IN_SQRTL:
+ 		fcode = BUILT_IN_SQRTF;
+ 		break;
+ 	      case BUILT_IN_SIN:
+ 	      case BUILT_IN_SINL:
+ 		fcode = BUILT_IN_SINF;
+ 		break;
+ 	      case BUILT_IN_COS:
+ 	      case BUILT_IN_COSL:
+ 		fcode = BUILT_IN_COSF;
+ 		break;
+ 	      case BUILT_IN_EXP:
+ 	      case BUILT_IN_EXPL:
+ 		fcode = BUILT_IN_EXPF;
+ 		break;
+ 	      default:
+ 		abort ();
+ 	      }
+ 	  else
+ 	    switch (fcode)
+ 	      {
+ 	      case BUILT_IN_SQRT:
+ 	      case BUILT_IN_SQRTL:
+ 		fcode = BUILT_IN_SQRT;
+ 		break;
+ 	      case BUILT_IN_SIN:
+ 	      case BUILT_IN_SINL:
+ 		fcode = BUILT_IN_SIN;
+ 		break;
+ 	      case BUILT_IN_COS:
+ 	      case BUILT_IN_COSL:
+ 		fcode = BUILT_IN_COS;
+ 		break;
+ 	      case BUILT_IN_EXP:
+ 	      case BUILT_IN_EXPL:
+ 		fcode = BUILT_IN_EXP;
+ 		break;
+ 	      default:
+ 		abort ();
+ 	      }
+ 
+ 	  /* ??? Fortran frontend does not initialize built_in_decls.
+ 	     For some reason creating the decl using builtin_function does not
+ 	     work as it should.   */
+ 	  if (built_in_decls [fcode])
+ 	    {
+ 	      arglist = build_tree_list (NULL_TREE, fold (convert_to_real (newtype, arg0)));
+ 	      expr = build_function_call_expr (built_in_decls [fcode], arglist);
+ 	      if (newtype == type)
+ 		return expr;
+ 	    }
+ 	}
+     }
+ 
+   /* Propagate the cast into the operation.  */
+   if (itype != type && FLOAT_TYPE_P (type))
+     switch (TREE_CODE (expr))
+       {
+ 	/* convert (float)-x into -(float)x.  This is always safe.  */
+ 	case ABS_EXPR:
+ 	case NEGATE_EXPR:
+ 	  return build1 (TREE_CODE (expr), type,
+ 			 fold (convert_to_real (type,
+ 						TREE_OPERAND (expr, 0))));
+ 	/* convert (outertype)((innertype0)a+(innertype1)b)
+ 	   into ((newtype)a+(newtype)b) where newtype
+ 	   is the widest mode from all of these.  */
+ 	case PLUS_EXPR:
+ 	case MINUS_EXPR:
+ 	case MULT_EXPR:
+ 	case RDIV_EXPR:
+ 	   {
+ 	     tree arg0 = strip_float_extensions (TREE_OPERAND (expr, 0));
+ 	     tree arg1 = strip_float_extensions (TREE_OPERAND (expr, 1));
+ 
+ 	     if (FLOAT_TYPE_P (TREE_TYPE (arg0))
+ 		 && FLOAT_TYPE_P (TREE_TYPE (arg1)))
+ 	       {
+ 		  tree newtype = type;
+ 		  if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (newtype))
+ 		    newtype = TREE_TYPE (arg0);
+ 		  if (TYPE_PRECISION (TREE_TYPE (arg1)) > TYPE_PRECISION (newtype))
+ 		    newtype = TREE_TYPE (arg1);
+ 		  if (TYPE_PRECISION (newtype) < TYPE_PRECISION (itype))
+ 		    {
+ 		      expr = build (TREE_CODE (expr), newtype,
+ 				    fold (convert_to_real (newtype, arg0)),
+ 				    fold (convert_to_real (newtype, arg1)));
+ 		      if (newtype == type)
+ 			return expr;
+ 		    }
+ 	       }
+ 	   }
+ 	  break;
+ 	default:
+ 	  break;
+       }
+ 
    switch (TREE_CODE (TREE_TYPE (expr)))
      {
      case REAL_TYPE:


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