Commit 7e139075 by Richard Kenner

(fold, case CONVERT_EXPR): Don't remove an integer conversion when outer is FP…

(fold, case CONVERT_EXPR): Don't remove an integer conversion when outer is FP unless it doesn't change signedness...

(fold, case CONVERT_EXPR): Don't remove an integer conversion when
outer is FP unless it doesn't change signedness; rework code in this
area to be clearer.

From-SVN: r8724
parent c47decad
/* Fold a constant sub-tree into a single node for C-compiler /* Fold a constant sub-tree into a single node for C-compiler
Copyright (C) 1987, 1988, 1992, 1993, 1994 Free Software Foundation, Inc. Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -3358,59 +3358,69 @@ fold (expr) ...@@ -3358,59 +3358,69 @@ fold (expr)
if (TREE_TYPE (TREE_OPERAND (t, 0)) == TREE_TYPE (t)) if (TREE_TYPE (TREE_OPERAND (t, 0)) == TREE_TYPE (t))
return TREE_OPERAND (t, 0); return TREE_OPERAND (t, 0);
/* In addition to the cases of two conversions in a row /* Handle cases of two conversions in a row. */
handled below, if we are converting something to its own if (TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR
type via an object of identical or wider precision, neither || TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR)
conversion is needed. */ {
if ((TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR tree inside_type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
|| TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR) tree inter_type = TREE_TYPE (TREE_OPERAND (t, 0));
&& TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) == TREE_TYPE (t) tree final_type = TREE_TYPE (t);
&& ((INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))) int inside_int = INTEGRAL_TYPE_P (inside_type);
&& INTEGRAL_TYPE_P (TREE_TYPE (t))) int inside_ptr = TREE_CODE (inside_type) == POINTER_TYPE;
|| (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))) int inside_float = FLOAT_TYPE_P (inside_type);
&& FLOAT_TYPE_P (TREE_TYPE (t)))) int inside_prec = TYPE_PRECISION (inside_type);
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0))) int inside_unsignedp = TREE_UNSIGNED (inside_type);
>= TYPE_PRECISION (TREE_TYPE (t)))) int inter_int = INTEGRAL_TYPE_P (inter_type);
return TREE_OPERAND (TREE_OPERAND (t, 0), 0); int inter_ptr = TREE_CODE (inter_type) == POINTER_TYPE;
int inter_float = FLOAT_TYPE_P (inter_type);
/* Two conversions in a row are not needed unless: int inter_prec = TYPE_PRECISION (inter_type);
- the intermediate type is narrower than both initial and final, or int inter_unsignedp = TREE_UNSIGNED (inter_type);
- the intermediate type and innermost type differ in signedness, int final_int = INTEGRAL_TYPE_P (final_type);
and the outermost type is wider than the intermediate, or int final_ptr = TREE_CODE (final_type) == POINTER_TYPE;
- the initial type is a pointer type and the precisions of the int final_float = FLOAT_TYPE_P (final_type);
intermediate and final types differ, or int final_prec = TYPE_PRECISION (final_type);
- the final type is a pointer type and the precisions of the int final_unsignedp = TREE_UNSIGNED (final_type);
initial and intermediate types differ. */
if ((TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR /* In addition to the cases of two conversions in a row
|| TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR) handled below, if we are converting something to its own
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0))) type via an object of identical or wider precision, neither
> TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))) conversion is needed. */
|| if (inside_type == final_type
TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0))) && ((inter_int && final_int) || (inter_float && final_float))
> TYPE_PRECISION (TREE_TYPE (t))) && inter_prec >= final_prec)
&& ! ((TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))) return TREE_OPERAND (TREE_OPERAND (t, 0), 0);
== INTEGER_TYPE)
&& (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) /* Likewise, if the intermediate and final types are either both
== INTEGER_TYPE) float or both integer, we don't need the middle conversion if
&& (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t, 0))) it is wider than the final type and doesn't change the signedness
!= TREE_UNSIGNED (TREE_OPERAND (TREE_OPERAND (t, 0), 0))) (for integers). */
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0))) if ((((inter_int || inter_ptr) && (inside_int || inside_ptr))
< TYPE_PRECISION (TREE_TYPE (t)))) || (inter_float && inside_float))
&& ((TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t, 0))) && inter_prec >= inside_prec
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0))) && (inter_float || inter_unsignedp == inside_unsignedp))
> TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))))) return convert (final_type, TREE_OPERAND (TREE_OPERAND (t, 0), 0));
==
(TREE_UNSIGNED (TREE_TYPE (t)) /* Two conversions in a row are not needed unless:
&& (TYPE_PRECISION (TREE_TYPE (t)) - some conversion is floating-point (overstrict for now), or
> TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0)))))) - the intermediate type is narrower than both initial and
&& ! ((TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))) final, or
== POINTER_TYPE) - the intermediate type and innermost type differ in signedness,
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0))) and the outermost type is wider than the intermediate, or
!= TYPE_PRECISION (TREE_TYPE (t)))) - the initial type is a pointer type and the precisions of the
&& ! (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE intermediate and final types differ, or
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))) - the final type is a pointer type and the precisions of the
!= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0)))))) initial and intermediate types differ. */
return convert (TREE_TYPE (t), TREE_OPERAND (TREE_OPERAND (t, 0), 0)); if (! inside_float && ! inter_float && ! final_float
&& (inter_prec > inside_prec || inter_prec > final_prec)
&& ! (inside_int && inter_int
&& inter_unsignedp != inside_unsignedp
&& inter_prec < final_prec)
&& ((inter_unsignedp && inter_prec > inside_prec)
== (final_unsignedp && final_prec > inter_prec))
&& ! (inside_ptr && inter_prec != final_prec)
&& ! (final_ptr && inside_prec != inter_prec))
return convert (final_type, TREE_OPERAND (TREE_OPERAND (t, 0), 0));
}
if (TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR if (TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR
&& TREE_CONSTANT (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) && TREE_CONSTANT (TREE_OPERAND (TREE_OPERAND (t, 0), 1))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment