diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-07-04 16:26:53 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-07-04 16:26:53 +0000 |
commit | f757850a1d54af91a5114d1616991cde2b833d05 (patch) | |
tree | 79ba821ded023f496e32c6557d2cc237570ca3e6 /gcc/tree-ssa.c | |
parent | 5d1f88800aabf4f38ab4bfcc83a87cb8aeb56ae0 (diff) | |
download | gcc-f757850a1d54af91a5114d1616991cde2b833d05.tar.gz |
2007-07-04 Richard Guenther <rguenther@suse.de>
* tree-ssa.c (useless_type_conversion_p): Add handling for
scalar float and vector types. Only call the types_compatible_p
langhook for aggregate types as last resort. Follow the
rules.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@126326 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r-- | gcc/tree-ssa.c | 94 |
1 files changed, 68 insertions, 26 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 8b2d8522252..005d3fdcbdd 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -908,13 +908,15 @@ delete_tree_ssa (void) 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. - - ??? The above do not hold currently. */ + to T* are not. */ bool useless_type_conversion_p (tree outer_type, tree inner_type) { + /* 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; @@ -951,43 +953,58 @@ useless_type_conversion_p (tree outer_type, tree inner_type) TYPE_MAX_VALUE (outer_type))) return false; - /* ??? We might want to preserve base type changes because of - TBAA. Or we need to be extra careful below. */ - 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; + /* We need to take special care recursing to pointed-to types. */ else if (POINTER_TYPE_P (inner_type) && POINTER_TYPE_P (outer_type)) { + /* If the outer type is (void *), then the conversion is not + necessary. */ + if (TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE) + return true; + /* Don't lose casts between pointers to volatile and non-volatile qualified types. Doing so would result in changing the semantics of later accesses. */ - if (TYPE_VOLATILE (TREE_TYPE (outer_type)) - != TYPE_VOLATILE (TREE_TYPE (inner_type))) + if ((TYPE_VOLATILE (TREE_TYPE (outer_type)) + != TYPE_VOLATILE (TREE_TYPE (inner_type))) + && TYPE_VOLATILE (TREE_TYPE (outer_type))) return false; /* Do not lose casts between pointers with different - TYPE_REF_CAN_ALIAS_ALL setting. */ - if (TYPE_REF_CAN_ALIAS_ALL (inner_type) - != TYPE_REF_CAN_ALIAS_ALL (outer_type)) + TYPE_REF_CAN_ALIAS_ALL setting or alias sets. */ + if ((TYPE_REF_CAN_ALIAS_ALL (inner_type) + != TYPE_REF_CAN_ALIAS_ALL (outer_type)) + || (get_alias_set (TREE_TYPE (inner_type)) + != get_alias_set (TREE_TYPE (outer_type)))) return false; - /* If the outer type is (void *), then the conversion is not - necessary. - ??? Together with calling the langhook below this makes - useless_type_conversion_p not transitive. */ - if (TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE) - return true; + /* Do not lose casts from const qualified to non-const + qualified. */ + if ((TYPE_READONLY (TREE_TYPE (outer_type)) + != TYPE_READONLY (TREE_TYPE (inner_type))) + && TYPE_READONLY (TREE_TYPE (inner_type))) + return false; + + /* Do not lose casts to restrict qualified pointers. */ + if ((TYPE_RESTRICT (outer_type) + != TYPE_RESTRICT (inner_type)) + && TYPE_RESTRICT (outer_type)) + return false; /* Otherwise pointers/references are equivalent if their pointed - to types are effectively the same. This allows to strip conversions - between pointer types with different type qualifiers. - ??? We should recurse here with - useless_type_conversion_p. */ - return lang_hooks.types_compatible_p (TREE_TYPE (inner_type), - TREE_TYPE (outer_type)); + to types are effectively the same. We can strip qualifiers + on pointed-to types for further comparsion, which is done in + the callee. */ + return useless_type_conversion_p (TREE_TYPE (outer_type), + TREE_TYPE (inner_type)); } /* Recurse for complex types. */ @@ -996,9 +1013,34 @@ useless_type_conversion_p (tree outer_type, tree inner_type) return useless_type_conversion_p (TREE_TYPE (outer_type), TREE_TYPE (inner_type)); - /* Fall back to what the frontend thinks of type compatibility. - ??? This should eventually just return false. */ - return lang_hooks.types_compatible_p (inner_type, outer_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)); + + /* For aggregates we may need to fall back to structural equality + checks. */ + else if (AGGREGATE_TYPE_P (inner_type) + && AGGREGATE_TYPE_P (outer_type)) + { + /* Different types of aggregates are incompatible. */ + if (TREE_CODE (inner_type) != TREE_CODE (outer_type)) + return false; + + /* If we know the canonical types, compare them. */ + if (TYPE_CANONICAL (inner_type) + && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type)) + return true; + + /* ??? Add structural equivalence check. */ + + /* ??? This should eventually just return false. */ + return lang_hooks.types_compatible_p (inner_type, outer_type); + } + + return false; } /* Return true if a conversion from either type of TYPE1 and TYPE2 |