diff options
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r-- | gcc/tree-ssa.c | 256 |
1 files changed, 1 insertions, 255 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 83a265c43ac..48c997d7390 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -32,7 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "bitmap.h" #include "pointer-set.h" -#include "tree-flow.h" +#include "tree-ssa.h" #include "gimple.h" #include "tree-inline.h" #include "hashtab.h" @@ -1149,260 +1149,6 @@ delete_tree_ssa (void) redirect_edge_var_map_destroy (); } -/* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a - useless type conversion, otherwise return false. - - This function implicitly defines the middle-end type system. With - the notion of 'a < b' meaning that useless_type_conversion_p (a, b) - holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds, - the following invariants shall be fulfilled: - - 1) useless_type_conversion_p is transitive. - If a < b and b < c then a < c. - - 2) useless_type_conversion_p is not symmetric. - From a < b does not follow a > b. - - 3) Types define the available set of operations applicable to values. - A type conversion is useless if the operations for the target type - is a subset of the operations for the source type. For example - casts to void* are useless, casts from void* are not (void* can't - be dereferenced or offsetted, but copied, hence its set of operations - is a strict subset of that of all other data pointer types). Casts - to const T* are useless (can't be written to), casts from const T* - to T* are not. */ - -bool -useless_type_conversion_p (tree outer_type, tree inner_type) -{ - /* Do the following before stripping toplevel qualifiers. */ - if (POINTER_TYPE_P (inner_type) - && POINTER_TYPE_P (outer_type)) - { - /* Do not lose casts between pointers to different address spaces. */ - if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type)) - != TYPE_ADDR_SPACE (TREE_TYPE (inner_type))) - return false; - } - - /* From now on qualifiers on value types do not matter. */ - inner_type = TYPE_MAIN_VARIANT (inner_type); - outer_type = TYPE_MAIN_VARIANT (outer_type); - - if (inner_type == outer_type) - return true; - - /* If we know the canonical types, compare them. */ - if (TYPE_CANONICAL (inner_type) - && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type)) - return true; - - /* Changes in machine mode are never useless conversions unless we - deal with aggregate types in which case we defer to later checks. */ - if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type) - && !AGGREGATE_TYPE_P (inner_type)) - return false; - - /* If both the inner and outer types are integral types, then the - conversion is not necessary if they have the same mode and - signedness and precision, and both or neither are boolean. */ - if (INTEGRAL_TYPE_P (inner_type) - && INTEGRAL_TYPE_P (outer_type)) - { - /* Preserve changes in signedness or precision. */ - if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type) - || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type)) - return false; - - /* Preserve conversions to/from BOOLEAN_TYPE if types are not - of precision one. */ - if (((TREE_CODE (inner_type) == BOOLEAN_TYPE) - != (TREE_CODE (outer_type) == BOOLEAN_TYPE)) - && TYPE_PRECISION (outer_type) != 1) - return false; - - /* We don't need to preserve changes in the types minimum or - maximum value in general as these do not generate code - unless the types precisions are different. */ - return true; - } - - /* Scalar floating point types with the same mode are compatible. */ - else if (SCALAR_FLOAT_TYPE_P (inner_type) - && SCALAR_FLOAT_TYPE_P (outer_type)) - return true; - - /* Fixed point types with the same mode are compatible. */ - else if (FIXED_POINT_TYPE_P (inner_type) - && FIXED_POINT_TYPE_P (outer_type)) - return true; - - /* We need to take special care recursing to pointed-to types. */ - else if (POINTER_TYPE_P (inner_type) - && POINTER_TYPE_P (outer_type)) - { - /* Do not lose casts to function pointer types. */ - if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE) - && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE)) - return false; - - /* We do not care for const qualification of the pointed-to types - as const qualification has no semantic value to the middle-end. */ - - /* Otherwise pointers/references are equivalent. */ - return true; - } - - /* Recurse for complex types. */ - else if (TREE_CODE (inner_type) == COMPLEX_TYPE - && TREE_CODE (outer_type) == COMPLEX_TYPE) - return useless_type_conversion_p (TREE_TYPE (outer_type), - TREE_TYPE (inner_type)); - - /* Recurse for vector types with the same number of subparts. */ - else if (TREE_CODE (inner_type) == VECTOR_TYPE - && TREE_CODE (outer_type) == VECTOR_TYPE - && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type)) - return useless_type_conversion_p (TREE_TYPE (outer_type), - TREE_TYPE (inner_type)); - - else if (TREE_CODE (inner_type) == ARRAY_TYPE - && TREE_CODE (outer_type) == ARRAY_TYPE) - { - /* Preserve string attributes. */ - if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type)) - return false; - - /* Conversions from array types with unknown extent to - array types with known extent are not useless. */ - if (!TYPE_DOMAIN (inner_type) - && TYPE_DOMAIN (outer_type)) - return false; - - /* Nor are conversions from array types with non-constant size to - array types with constant size or to different size. */ - if (TYPE_SIZE (outer_type) - && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST - && (!TYPE_SIZE (inner_type) - || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST - || !tree_int_cst_equal (TYPE_SIZE (outer_type), - TYPE_SIZE (inner_type)))) - return false; - - /* Check conversions between arrays with partially known extents. - If the array min/max values are constant they have to match. - Otherwise allow conversions to unknown and variable extents. - In particular this declares conversions that may change the - mode to BLKmode as useless. */ - if (TYPE_DOMAIN (inner_type) - && TYPE_DOMAIN (outer_type) - && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type)) - { - tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type)); - tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type)); - tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type)); - tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type)); - - /* After gimplification a variable min/max value carries no - additional information compared to a NULL value. All that - matters has been lowered to be part of the IL. */ - if (inner_min && TREE_CODE (inner_min) != INTEGER_CST) - inner_min = NULL_TREE; - if (outer_min && TREE_CODE (outer_min) != INTEGER_CST) - outer_min = NULL_TREE; - if (inner_max && TREE_CODE (inner_max) != INTEGER_CST) - inner_max = NULL_TREE; - if (outer_max && TREE_CODE (outer_max) != INTEGER_CST) - outer_max = NULL_TREE; - - /* Conversions NULL / variable <- cst are useless, but not - the other way around. */ - if (outer_min - && (!inner_min - || !tree_int_cst_equal (inner_min, outer_min))) - return false; - if (outer_max - && (!inner_max - || !tree_int_cst_equal (inner_max, outer_max))) - return false; - } - - /* Recurse on the element check. */ - return useless_type_conversion_p (TREE_TYPE (outer_type), - TREE_TYPE (inner_type)); - } - - else if ((TREE_CODE (inner_type) == FUNCTION_TYPE - || TREE_CODE (inner_type) == METHOD_TYPE) - && TREE_CODE (inner_type) == TREE_CODE (outer_type)) - { - tree outer_parm, inner_parm; - - /* If the return types are not compatible bail out. */ - if (!useless_type_conversion_p (TREE_TYPE (outer_type), - TREE_TYPE (inner_type))) - return false; - - /* Method types should belong to a compatible base class. */ - if (TREE_CODE (inner_type) == METHOD_TYPE - && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type), - TYPE_METHOD_BASETYPE (inner_type))) - return false; - - /* A conversion to an unprototyped argument list is ok. */ - if (!prototype_p (outer_type)) - return true; - - /* If the unqualified argument types are compatible the conversion - is useless. */ - if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type)) - return true; - - for (outer_parm = TYPE_ARG_TYPES (outer_type), - inner_parm = TYPE_ARG_TYPES (inner_type); - outer_parm && inner_parm; - outer_parm = TREE_CHAIN (outer_parm), - inner_parm = TREE_CHAIN (inner_parm)) - if (!useless_type_conversion_p - (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)), - TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm)))) - return false; - - /* If there is a mismatch in the number of arguments the functions - are not compatible. */ - if (outer_parm || inner_parm) - return false; - - /* Defer to the target if necessary. */ - if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type)) - return comp_type_attributes (outer_type, inner_type) != 0; - - return true; - } - - /* For aggregates we rely on TYPE_CANONICAL exclusively and require - explicit conversions for types involving to be structurally - compared types. */ - else if (AGGREGATE_TYPE_P (inner_type) - && TREE_CODE (inner_type) == TREE_CODE (outer_type)) - return false; - - return false; -} - -/* Return true if a conversion from either type of TYPE1 and TYPE2 - to the other is not required. Otherwise return false. */ - -bool -types_compatible_p (tree type1, tree type2) -{ - return (type1 == type2 - || (useless_type_conversion_p (type1, type2) - && useless_type_conversion_p (type2, type1))); -} - /* Return true if EXPR is a useless type conversion, otherwise return false. */ |