This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
As discussed in previous posts of this patch, this makes useless_type_conversion_p handle all cases but aggregate types with middle-end only logic. The constraints we follow are those set by the comments of useless_type_conversion_p. I'm currently re-bootstrapping and testing this patch and I'll give it a run on our nightly performance tester as well. If there are no further concerns about this patch I will go ahead and commit this tomorrow if the performance testing didn't show anything bad. Thanks, Richard. 2007-06-22 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. Index: gcc/tree-ssa.c =================================================================== *** gcc.orig/tree-ssa.c 2007-07-02 14:22:13.000000000 +0200 --- gcc/tree-ssa.c 2007-07-02 14:34:46.000000000 +0200 *************** delete_tree_ssa (void) *** 908,920 **** 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. */ bool useless_type_conversion_p (tree outer_type, tree inner_type) { if (inner_type == outer_type) return true; --- 908,922 ---- 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) { + /* 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; *************** useless_type_conversion_p (tree outer_ty *** 951,993 **** 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; } /* We need to take special care recursing to pointed-to types. */ else if (POINTER_TYPE_P (inner_type) && POINTER_TYPE_P (outer_type)) { /* 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))) 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)) 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; /* 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)); } /* Recurse for complex types. */ --- 953,1010 ---- TYPE_MAX_VALUE (outer_type))) return false; 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))) ! && TYPE_VOLATILE (TREE_TYPE (outer_type))) return false; /* Do not lose casts between pointers with different ! 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; ! /* 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. 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. */ *************** useless_type_conversion_p (tree outer_ty *** 996,1004 **** 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); } /* Return true if a conversion from either type of TYPE1 and TYPE2 --- 1013,1047 ---- 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)); ! ! /* 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 (TREE_TYPE (inner_type), ! TREE_TYPE (outer_type)); ! } ! ! return false; } /* Return true if a conversion from either type of TYPE1 and TYPE2
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |