diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 18e9586769a..02646a702d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2007-08-24 Richard Guenther + + PR middle-end/33166 + * tree-ssa.c (useless_type_conversion_p): Split into a + recursive and a non-recursive part. + (useless_type_conversion_p_1): New function. + * tree-ssa-ccp.c (fold_stmt_r): Make sure that the result + from maybe_fold_offset_to_reference is trivially convertible + to the desired type before doing the simplification. + 2007-08-24 Jakub Jelinek * expr.c (store_expr): Optimize initialization of an array diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a27c2ad411e..54da80e5169 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-08-24 Richard Guenther + + PR middle-end/33166 + * gcc.c-torture/compile/pr33166.c: New testcase. + 2007-08-24 Tobias Burnus PR fortran/33139 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr33166.c b/gcc/testsuite/gcc.c-torture/compile/pr33166.c new file mode 100644 index 00000000000..a48c529c3fe --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr33166.c @@ -0,0 +1,10 @@ +static void ConvertAddr (char *saddr, void **addr) +{ + *addr = (void *) &saddr; +} +void DefineSelf (char *addr) +{ + ConvertAddr (addr, (void **) &addr); + if (addr[0] == 127 && addr[3] == 1) + ; +} diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index e6dfcd83e88..e0829f59917 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -2060,7 +2060,12 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) (TREE_OPERAND (expr, 0), integer_zero_node, TREE_TYPE (TREE_TYPE (expr))))) - t = build_fold_addr_expr_with_type (t, TREE_TYPE (expr)); + { + tree ptr_type = build_pointer_type (TREE_TYPE (t)); + if (!useless_type_conversion_p (TREE_TYPE (expr), ptr_type)) + return NULL_TREE; + t = build_fold_addr_expr_with_type (t, ptr_type); + } break; /* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF. diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index e0885497e11..633e446fe1a 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -885,32 +885,10 @@ delete_tree_ssa (void) cfun->gimple_df = NULL; } +/* Helper function for useless_type_conversion_p. */ -/* 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) +static bool +useless_type_conversion_p_1 (tree outer_type, tree inner_type) { /* Qualifiers on value types do not matter. */ inner_type = TYPE_MAIN_VARIANT (inner_type); @@ -964,11 +942,6 @@ useless_type_conversion_p (tree outer_type, tree inner_type) 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. */ @@ -1002,22 +975,22 @@ useless_type_conversion_p (tree outer_type, tree inner_type) to types are effectively the same. We can strip qualifiers on pointed-to types for further comparison, which is done in the callee. */ - return useless_type_conversion_p (TREE_TYPE (outer_type), - TREE_TYPE (inner_type)); + return useless_type_conversion_p_1 (TREE_TYPE (outer_type), + TREE_TYPE (inner_type)); } /* 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)); + return useless_type_conversion_p_1 (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)); + return useless_type_conversion_p_1 (TREE_TYPE (outer_type), + TREE_TYPE (inner_type)); /* For aggregates we may need to fall back to structural equality checks. */ @@ -1037,6 +1010,43 @@ useless_type_conversion_p (tree outer_type, tree inner_type) return false; } +/* 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) +{ + /* If the outer type is (void *), then the conversion is not + necessary. We have to make sure to not apply this while + recursing though. */ + if (POINTER_TYPE_P (inner_type) + && POINTER_TYPE_P (outer_type) + && TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE) + return true; + + return useless_type_conversion_p_1 (outer_type, inner_type); +} + /* Return true if a conversion from either type of TYPE1 and TYPE2 to the other is not required. Otherwise return false. */