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
|
@ -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>
|
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
|
||||||
|
|
|
@ -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>
|
2007-08-24 Tobias Burnus <burnus@net-b.de>
|
||||||
|
|
||||||
PR fortran/33139
|
PR fortran/33139
|
||||||
|
|
|
@ -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),
|
(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)
|
||||||
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)
|
||||||
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,21 +975,21 @@ 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
|
||||||
|
@ -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. */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue