diff options
| author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-09 21:56:35 +0000 | 
|---|---|---|
| committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-02-09 21:56:35 +0000 | 
| commit | 198d9bbee87d11cad4547476146f84d5495c0260 (patch) | |
| tree | b165cf0028ec1a832fc59f34df44d639c9c318a2 /gcc/fold-const.c | |
| parent | d1001cc93ca3fc8a93e1048911c52dab4a56d6da (diff) | |
| download | ppe42-gcc-198d9bbee87d11cad4547476146f84d5495c0260.tar.gz ppe42-gcc-198d9bbee87d11cad4547476146f84d5495c0260.zip | |
	* fold-const.c (fold_strip_sign_ops): New function to simplify a
	floating point expression ignoring the sign of the result.
	(fold) <ABS_EXPR>: Use it to simplify fabs(x).
	(fold) <MULT_EXPR>: Use it to simplify x*x.
	* tree.h (fold_strip_sign_ops): Prototype here.
	* builtins.c (fold_builtin_copysign): Take an additional FNDECL
	argument.  Use fold_strip_sign_ops to simplify the first argument.
	(fold_builtin_pow):  Use fold_strip_sign_ops to simplify the
	first argument when the second argument is an even integer
	constant, but only with -funsafe_math_optimizations.
	(fold_builtin_1): Update call to fold_builtin_copysign.
	* gcc.dg/builtins-48.c: New test case.
	* gcc.dg/builtins-49.c: New test case.
	* gcc.dg/builtins-50.c: New test case.
	* gcc.dg/builtins-51.c: New test case.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94779 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
| -rw-r--r-- | gcc/fold-const.c | 54 | 
1 files changed, 54 insertions, 0 deletions
| diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 294f94cbf1b..de54258c2a4 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6776,6 +6776,14 @@ fold (tree expr)  	}        else if (tree_expr_nonnegative_p (arg0))  	return arg0; + +      /* Strip sign ops from argument.  */ +      if (TREE_CODE (type) == REAL_TYPE) +	{ +	  tem = fold_strip_sign_ops (arg0); +	  if (tem) +	    return fold (build1 (ABS_EXPR, type, fold_convert (type, tem))); +	}        return t;      case CONJ_EXPR: @@ -7429,6 +7437,17 @@ fold (tree expr)  				     TREE_OPERAND (arg0, 1)));  	    } +          /* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y.  */ +	  if (operand_equal_p (arg0, arg1, 0)) +	    { +	      tree tem = fold_strip_sign_ops (arg0); +	      if (tem != NULL_TREE) +		{ +		  tem = fold_convert (type, tem); +		  return fold (build2 (MULT_EXPR, type, tem, tem)); +		} +	    } +  	  if (flag_unsafe_math_optimizations)  	    {  	      enum built_in_function fcode0 = builtin_mathfn_code (arg0); @@ -11229,3 +11248,38 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)    *diff += (bitpos1 - bitpos2) / BITS_PER_UNIT;    return true;  } + +/* Simplify the floating point expression EXP when the sign of the +   result is not significant.  Return NULL_TREE if no simplification +   is possible.  */ + +tree +fold_strip_sign_ops (tree exp) +{ +  tree arg0, arg1; + +  switch (TREE_CODE (exp)) +    { +    case ABS_EXPR: +    case NEGATE_EXPR: +      arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0)); +      return arg0 ? arg0 : TREE_OPERAND (exp, 0); + +    case MULT_EXPR: +    case RDIV_EXPR: +      if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (exp)))) +	return NULL_TREE; +      arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0)); +      arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1)); +      if (arg0 != NULL_TREE || arg1 != NULL_TREE) +	return fold (build2 (TREE_CODE (exp), TREE_TYPE (exp), +			     arg0 ? arg0 : TREE_OPERAND (exp, 0), +			     arg1 ? arg1 : TREE_OPERAND (exp, 1))); +      break; + +    default: +      break; +    } +  return NULL_TREE; +} + | 

