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:
parent
a7d318ea7f
commit
fa2050d266
5 changed files with 77 additions and 37 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
10
gcc/testsuite/gcc.c-torture/compile/pr33166.c
Normal file
10
gcc/testsuite/gcc.c-torture/compile/pr33166.c
Normal 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)
|
||||
;
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue