Commit fa2050d2 by Richard Guenther Committed by Richard Biener

re PR tree-optimization/33166 (ICE in get_indirect_ref_operands, at tree-ssa-operands.c:1698)

2007-08-24  Richard Guenther  <rguenther@suse.de>

	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.

	* gcc.c-torture/compile/pr33166.c: New testcase.

From-SVN: r127771
parent a7d318ea
2007-08-24 Richard Guenther <rguenther@suse.de>
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 <jakub@redhat.com> 2007-08-24 Jakub Jelinek <jakub@redhat.com>
* expr.c (store_expr): Optimize initialization of an array * expr.c (store_expr): Optimize initialization of an array
......
2007-08-24 Richard Guenther <rguenther@suse.de>
PR middle-end/33166
* gcc.c-torture/compile/pr33166.c: New testcase.
2007-08-24 Tobias Burnus <burnus@net-b.de> 2007-08-24 Tobias Burnus <burnus@net-b.de>
PR fortran/33139 PR fortran/33139
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)
;
}
...@@ -2060,7 +2060,12 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) ...@@ -2060,7 +2060,12 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
(TREE_OPERAND (expr, 0), (TREE_OPERAND (expr, 0),
integer_zero_node, integer_zero_node,
TREE_TYPE (TREE_TYPE (expr))))) 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; break;
/* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF. /* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF.
......
...@@ -885,32 +885,10 @@ delete_tree_ssa (void) ...@@ -885,32 +885,10 @@ delete_tree_ssa (void)
cfun->gimple_df = NULL; cfun->gimple_df = NULL;
} }
/* Helper function for useless_type_conversion_p. */
/* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a static bool
useless type conversion, otherwise return false. useless_type_conversion_p_1 (tree outer_type, tree inner_type)
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)
{ {
/* Qualifiers on value types do not matter. */ /* Qualifiers on value types do not matter. */
inner_type = TYPE_MAIN_VARIANT (inner_type); inner_type = TYPE_MAIN_VARIANT (inner_type);
...@@ -964,11 +942,6 @@ useless_type_conversion_p (tree outer_type, tree inner_type) ...@@ -964,11 +942,6 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
else if (POINTER_TYPE_P (inner_type) else if (POINTER_TYPE_P (inner_type)
&& POINTER_TYPE_P (outer_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 /* Don't lose casts between pointers to volatile and non-volatile
qualified types. Doing so would result in changing the semantics qualified types. Doing so would result in changing the semantics
of later accesses. */ of later accesses. */
...@@ -1002,22 +975,22 @@ useless_type_conversion_p (tree outer_type, tree inner_type) ...@@ -1002,22 +975,22 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
to types are effectively the same. We can strip qualifiers to types are effectively the same. We can strip qualifiers
on pointed-to types for further comparison, which is done in on pointed-to types for further comparison, which is done in
the callee. */ the callee. */
return useless_type_conversion_p (TREE_TYPE (outer_type), return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
TREE_TYPE (inner_type)); TREE_TYPE (inner_type));
} }
/* Recurse for complex types. */ /* Recurse for complex types. */
else if (TREE_CODE (inner_type) == COMPLEX_TYPE else if (TREE_CODE (inner_type) == COMPLEX_TYPE
&& TREE_CODE (outer_type) == COMPLEX_TYPE) && TREE_CODE (outer_type) == COMPLEX_TYPE)
return useless_type_conversion_p (TREE_TYPE (outer_type), return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
TREE_TYPE (inner_type)); TREE_TYPE (inner_type));
/* Recurse for vector types with the same number of subparts. */ /* Recurse for vector types with the same number of subparts. */
else if (TREE_CODE (inner_type) == VECTOR_TYPE else if (TREE_CODE (inner_type) == VECTOR_TYPE
&& TREE_CODE (outer_type) == VECTOR_TYPE && TREE_CODE (outer_type) == VECTOR_TYPE
&& TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type)) && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
return useless_type_conversion_p (TREE_TYPE (outer_type), return useless_type_conversion_p_1 (TREE_TYPE (outer_type),
TREE_TYPE (inner_type)); TREE_TYPE (inner_type));
/* For aggregates we may need to fall back to structural equality /* For aggregates we may need to fall back to structural equality
checks. */ checks. */
...@@ -1037,6 +1010,43 @@ useless_type_conversion_p (tree outer_type, tree inner_type) ...@@ -1037,6 +1010,43 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
return false; 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 /* Return true if a conversion from either type of TYPE1 and TYPE2
to the other is not required. Otherwise return false. */ to the other is not required. Otherwise return false. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment