summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r--gcc/tree-ssa.c256
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. */