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
This commit is contained in:
Richard Guenther 2007-08-24 15:09:10 +00:00 committed by Richard Biener
parent a7d318ea7f
commit fa2050d266
5 changed files with 77 additions and 37 deletions

View File

@ -1,3 +1,13 @@
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>
* expr.c (store_expr): Optimize initialization of an array

View File

@ -1,3 +1,8 @@
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>
PR fortran/33139

View File

@ -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)
;
}

View File

@ -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.

View File

@ -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. */