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]

[Committed] Bug combining type conversions in fold-const.c


The following patch fixes a latent bug in GCC's constant folding.  fold
contains code to combine two consecutive type conversions into a single
conversion when possible.  Examples of which include the following
problematic cases:

	(FIX_TRUNC_EXPR:int (NOP_EXPR:double (...:float))
	(FIX_CEIL_EXPR:int (NOP_EXPR:double (...:float))
	(FIX_FLOOR_EXPR:int (NOP_EXPR:double (...:float))

where the conversion to an integer can be performed as a float->int
conversion rather than as a float->double extension followed by a
double->int conversion.

The problem is that instead of using the original FP->int conversion
operator, fold previously called the front-end's "convert" function
which would apply the default integer to fp conversion for that
language, FIX_TRUNC_EXPR for C/C++ or perform rounding in FORTRAN.

This issue was exposed by my recent patch to provide a language
independent "fold_convert" for use by the middle-end (i.e. without
generating warnings, etc...).  As theoretically, fold_convert never
needs to suggest a default real->integer conversion it just calls
abort.  To my surprise this abort triggered whilst compiling 175.vpr
from SPECint2000, revealing the latent bug fixed below.


The following patch has been tested by a full bootstrap on
i686-pc-linux-gnu, all languages except treelang, and regression
tested with a top-level "make -k check" with no new failures.

Committed to mainline.



2004-02-09  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (fold) <NOP_EXPR>: Use the original type conversion
	tree code rather than call fold_convert, which doesn't specify a
	default floating point to integer conversion.

	* gcc.c-torture/compile/20040209-1.c: New test case.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.328
diff -c -3 -p -r1.328 fold-const.c
*** fold-const.c	7 Feb 2004 18:57:29 -0000	1.328
--- fold-const.c	8 Feb 2004 23:54:07 -0000
*************** fold (tree expr)
*** 5641,5648 ****
  	  if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (final_type)
  	      && ((inter_int && final_int) || (inter_float && final_float))
  	      && inter_prec >= final_prec)
! 	    return fold_convert (final_type,
! 				 TREE_OPERAND (TREE_OPERAND (t, 0), 0));

  	  /* Likewise, if the intermediate and final types are either both
  	     float or both integer, we don't need the middle conversion if
--- 5641,5648 ----
  	  if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (final_type)
  	      && ((inter_int && final_int) || (inter_float && final_float))
  	      && inter_prec >= final_prec)
! 	    return fold (build1 (code, final_type,
! 				 TREE_OPERAND (TREE_OPERAND (t, 0), 0)));

  	  /* Likewise, if the intermediate and final types are either both
  	     float or both integer, we don't need the middle conversion if
*************** fold (tree expr)
*** 5657,5672 ****
  	      && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type))
  		    && TYPE_MODE (final_type) == TYPE_MODE (inter_type))
  	      && ! final_ptr)
! 	    return fold_convert (final_type,
! 				 TREE_OPERAND (TREE_OPERAND (t, 0), 0));

  	  /* If we have a sign-extension of a zero-extended value, we can
  	     replace that by a single zero-extension.  */
  	  if (inside_int && inter_int && final_int
  	      && inside_prec < inter_prec && inter_prec < final_prec
  	      && inside_unsignedp && !inter_unsignedp)
! 	    return fold_convert (final_type,
! 				 TREE_OPERAND (TREE_OPERAND (t, 0), 0));

  	  /* Two conversions in a row are not needed unless:
  	     - some conversion is floating-point (overstrict for now), or
--- 5657,5672 ----
  	      && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type))
  		    && TYPE_MODE (final_type) == TYPE_MODE (inter_type))
  	      && ! final_ptr)
! 	    return fold (build1 (code, final_type,
! 				 TREE_OPERAND (TREE_OPERAND (t, 0), 0)));

  	  /* If we have a sign-extension of a zero-extended value, we can
  	     replace that by a single zero-extension.  */
  	  if (inside_int && inter_int && final_int
  	      && inside_prec < inter_prec && inter_prec < final_prec
  	      && inside_unsignedp && !inter_unsignedp)
! 	    return fold (build1 (code, final_type,
! 				 TREE_OPERAND (TREE_OPERAND (t, 0), 0)));

  	  /* Two conversions in a row are not needed unless:
  	     - some conversion is floating-point (overstrict for now), or
*************** fold (tree expr)
*** 5690,5697 ****
  	      && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type))
  		    && TYPE_MODE (final_type) == TYPE_MODE (inter_type))
  	      && ! final_ptr)
! 	    return fold_convert (final_type,
! 				 TREE_OPERAND (TREE_OPERAND (t, 0), 0));
  	}

        if (TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR
--- 5690,5697 ----
  	      && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (final_type))
  		    && TYPE_MODE (final_type) == TYPE_MODE (inter_type))
  	      && ! final_ptr)
! 	    return fold (build1 (code, final_type,
! 				 TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
  	}

        if (TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR


/* The following code used to ICE in fold_convert.  */

float ceilf(float);

int foo(float x)
{
  return (double)ceilf(x);
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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