mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 12:21:15 +08:00
re PR middle-end/37742 (ICE in vectorizer with restrict pointer)
2008-11-05 Richard Guenther <rguenther@suse.de> PR middle-end/37742 * tree-ssa.c (useless_type_conversion_p_1): Check different restrict qualified pointer conversion before stripping qualifiers. * gimplify.c (create_tmp_from_val): Use correctly qualified type. * tree-flow.h (may_propagate_address_into_dereference): Declare. * tree-ssa-ccp.c (may_propagate_address_into_dereference): New function. (ccp_fold): Use it. * tree-ssa-forwprop.c (rhs_to_tree): Remove useless conversions, properly canonicalize binary ops. (forward_propagate_addr_expr_1): Use may_propagate_address_into_dereference. cp/ * decl.c (start_preparsed_function): Use the correct type for building the RESULT_DECL. * gcc.c-torture/compile/pr37742.c: New testcase. * g++.dg/pr37742.C: Likewise. * gcc.dg/tree-ssa/forwprop-7.c: Check for two volatile loads. From-SVN: r141606
This commit is contained in:
parent
08906bf8a2
commit
f7c0ffb441
@ -1,3 +1,17 @@
|
||||
2008-11-05 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/37742
|
||||
* tree-ssa.c (useless_type_conversion_p_1): Check different restrict
|
||||
qualified pointer conversion before stripping qualifiers.
|
||||
* gimplify.c (create_tmp_from_val): Use correctly qualified type.
|
||||
* tree-flow.h (may_propagate_address_into_dereference): Declare.
|
||||
* tree-ssa-ccp.c (may_propagate_address_into_dereference): New function.
|
||||
(ccp_fold): Use it.
|
||||
* tree-ssa-forwprop.c (rhs_to_tree): Remove useless conversions,
|
||||
properly canonicalize binary ops.
|
||||
(forward_propagate_addr_expr_1): Use
|
||||
may_propagate_address_into_dereference.
|
||||
|
||||
2008-11-05 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR middle-end/37286
|
||||
|
@ -1,3 +1,9 @@
|
||||
2008-11-05 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/37742
|
||||
* decl.c (start_preparsed_function): Use the correct type for
|
||||
building the RESULT_DECL.
|
||||
|
||||
2008-10-31 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/37967
|
||||
|
@ -11492,7 +11492,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
|
||||
{
|
||||
tree resdecl;
|
||||
|
||||
resdecl = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
|
||||
resdecl = build_decl (RESULT_DECL, 0, restype);
|
||||
DECL_ARTIFICIAL (resdecl) = 1;
|
||||
DECL_IGNORED_P (resdecl) = 1;
|
||||
DECL_RESULT (decl1) = resdecl;
|
||||
|
@ -565,7 +565,7 @@ create_tmp_var (tree type, const char *prefix)
|
||||
static inline tree
|
||||
create_tmp_from_val (tree val)
|
||||
{
|
||||
return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val));
|
||||
return create_tmp_var (TREE_TYPE (val), get_name (val));
|
||||
}
|
||||
|
||||
/* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
|
||||
|
@ -1,3 +1,10 @@
|
||||
2008-11-05 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/37742
|
||||
* gcc.c-torture/compile/pr37742.c: New testcase.
|
||||
* g++.dg/pr37742.C: Likewise.
|
||||
* gcc.dg/tree-ssa/forwprop-7.c: Check for two volatile loads.
|
||||
|
||||
2008-11-05 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR middle-end/37286
|
||||
|
10
gcc/testsuite/g++.dg/pr37742.C
Normal file
10
gcc/testsuite/g++.dg/pr37742.C
Normal file
@ -0,0 +1,10 @@
|
||||
/* { dg-do compile } */
|
||||
|
||||
typedef long unsigned int size_t;
|
||||
void* __valarray_get_memory(size_t __n);
|
||||
int*__restrict__
|
||||
__valarray_get_storage(size_t __n)
|
||||
{
|
||||
return static_cast<int* __restrict__>(__valarray_get_memory(__n));
|
||||
}
|
||||
|
21
gcc/testsuite/gcc.c-torture/compile/pr37742.c
Normal file
21
gcc/testsuite/gcc.c-torture/compile/pr37742.c
Normal file
@ -0,0 +1,21 @@
|
||||
void foo(int* __restrict__ p, int* q, int* p1, int *q1)
|
||||
{
|
||||
int i;
|
||||
|
||||
p = p1;
|
||||
q = q1;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
*++q = *++p + 1;
|
||||
}
|
||||
|
||||
void bar(int* p, int* __restrict__ q, int* p1, int *q1)
|
||||
{
|
||||
int i;
|
||||
|
||||
p = p1;
|
||||
q = q1;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
*++q = *++p + 1;
|
||||
}
|
@ -8,7 +8,9 @@ int foo(void)
|
||||
return *p + *p;
|
||||
}
|
||||
|
||||
/* We should not convert the cast to a VCE in forwprop1 as we have a volatile reference. */
|
||||
/* We should not convert the cast to a VCE in forwprop1 as we have a
|
||||
volatile reference. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 0 "forwprop1"} } */
|
||||
/* { dg-final { scan-tree-dump-times "volatile int" 2 "forwprop1"} } */
|
||||
/* { dg-final { scan-tree-dump-times "={v}" 2 "forwprop1"} } */
|
||||
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
|
||||
|
@ -905,6 +905,8 @@ bool fold_stmt (gimple_stmt_iterator *);
|
||||
bool fold_stmt_inplace (gimple);
|
||||
tree get_symbol_constant_value (tree);
|
||||
tree fold_const_aggregate_ref (tree);
|
||||
bool may_propagate_address_into_dereference (tree, tree);
|
||||
|
||||
|
||||
/* In tree-vrp.c */
|
||||
tree vrp_evaluate_conditional (enum tree_code, tree, tree, gimple);
|
||||
|
@ -851,6 +851,31 @@ ccp_visit_phi_node (gimple phi)
|
||||
return SSA_PROP_NOT_INTERESTING;
|
||||
}
|
||||
|
||||
/* Return true if we may propagate the address expression ADDR into the
|
||||
dereference DEREF and cancel them. */
|
||||
|
||||
bool
|
||||
may_propagate_address_into_dereference (tree addr, tree deref)
|
||||
{
|
||||
gcc_assert (INDIRECT_REF_P (deref)
|
||||
&& TREE_CODE (addr) == ADDR_EXPR);
|
||||
|
||||
/* If the address is invariant then we do not need to preserve restrict
|
||||
qualifications. But we do need to preserve volatile qualifiers until
|
||||
we can annotate the folded dereference itself properly. */
|
||||
if (is_gimple_min_invariant (addr)
|
||||
&& (!TREE_THIS_VOLATILE (deref)
|
||||
|| TYPE_VOLATILE (TREE_TYPE (addr))))
|
||||
return useless_type_conversion_p (TREE_TYPE (deref),
|
||||
TREE_TYPE (TREE_OPERAND (addr, 0)));
|
||||
|
||||
/* Else both the address substitution and the folding must result in
|
||||
a valid useless type conversion sequence. */
|
||||
return (useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (deref, 0)),
|
||||
TREE_TYPE (addr))
|
||||
&& useless_type_conversion_p (TREE_TYPE (deref),
|
||||
TREE_TYPE (TREE_OPERAND (addr, 0))));
|
||||
}
|
||||
|
||||
/* CCP specific front-end to the non-destructive constant folding
|
||||
routines.
|
||||
@ -897,12 +922,8 @@ ccp_fold (gimple stmt)
|
||||
prop_value_t *val = get_value (TREE_OPERAND (*base, 0));
|
||||
if (val->lattice_val == CONSTANT
|
||||
&& TREE_CODE (val->value) == ADDR_EXPR
|
||||
&& useless_type_conversion_p
|
||||
(TREE_TYPE (TREE_OPERAND (*base, 0)),
|
||||
TREE_TYPE (val->value))
|
||||
&& useless_type_conversion_p
|
||||
(TREE_TYPE (*base),
|
||||
TREE_TYPE (TREE_OPERAND (val->value, 0))))
|
||||
&& may_propagate_address_into_dereference
|
||||
(val->value, *base))
|
||||
{
|
||||
/* We need to return a new tree, not modify the IL
|
||||
or share parts of it. So play some tricks to
|
||||
|
@ -334,10 +334,10 @@ rhs_to_tree (tree type, gimple stmt)
|
||||
{
|
||||
enum tree_code code = gimple_assign_rhs_code (stmt);
|
||||
if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS)
|
||||
return fold_convert (type, build2 (code, type, gimple_assign_rhs1 (stmt),
|
||||
gimple_assign_rhs2 (stmt)));
|
||||
return fold_build2 (code, type, gimple_assign_rhs1 (stmt),
|
||||
gimple_assign_rhs2 (stmt));
|
||||
else if (get_gimple_rhs_class (code) == GIMPLE_UNARY_RHS)
|
||||
return fold_convert (type, build1 (code, type, gimple_assign_rhs1 (stmt)));
|
||||
return build1 (code, type, gimple_assign_rhs1 (stmt));
|
||||
else if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
|
||||
return gimple_assign_rhs1 (stmt);
|
||||
else
|
||||
@ -719,12 +719,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
|
||||
propagate the ADDR_EXPR into the use of NAME and fold the result. */
|
||||
if (TREE_CODE (lhs) == INDIRECT_REF
|
||||
&& TREE_OPERAND (lhs, 0) == name
|
||||
&& useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (lhs, 0)),
|
||||
TREE_TYPE (def_rhs))
|
||||
/* ??? This looks redundant, but is required for bogus types
|
||||
that can sometimes occur. */
|
||||
&& useless_type_conversion_p (TREE_TYPE (lhs),
|
||||
TREE_TYPE (TREE_OPERAND (def_rhs, 0))))
|
||||
&& may_propagate_address_into_dereference (def_rhs, lhs))
|
||||
{
|
||||
*lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
|
||||
fold_stmt_inplace (use_stmt);
|
||||
@ -747,12 +742,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
|
||||
propagate the ADDR_EXPR into the use of NAME and fold the result. */
|
||||
if (TREE_CODE (rhs) == INDIRECT_REF
|
||||
&& TREE_OPERAND (rhs, 0) == name
|
||||
&& useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (rhs, 0)),
|
||||
TREE_TYPE (def_rhs))
|
||||
/* ??? This looks redundant, but is required for bogus types
|
||||
that can sometimes occur. */
|
||||
&& useless_type_conversion_p (TREE_TYPE (rhs),
|
||||
TREE_TYPE (TREE_OPERAND (def_rhs, 0))))
|
||||
&& may_propagate_address_into_dereference (def_rhs, rhs))
|
||||
{
|
||||
*rhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
|
||||
fold_stmt_inplace (use_stmt);
|
||||
|
@ -1071,7 +1071,18 @@ delete_tree_ssa (void)
|
||||
static bool
|
||||
useless_type_conversion_p_1 (tree outer_type, tree inner_type)
|
||||
{
|
||||
/* Qualifiers on value types do not matter. */
|
||||
/* Do the following before stripping toplevel qualifiers. */
|
||||
if (POINTER_TYPE_P (inner_type)
|
||||
&& POINTER_TYPE_P (outer_type))
|
||||
{
|
||||
/* Do not lose casts to restrict qualified pointers. */
|
||||
if ((TYPE_RESTRICT (outer_type)
|
||||
!= TYPE_RESTRICT (inner_type))
|
||||
&& TYPE_RESTRICT (outer_type))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* From now on qualifiers on value types do not matter. */
|
||||
inner_type = TYPE_MAIN_VARIANT (inner_type);
|
||||
outer_type = TYPE_MAIN_VARIANT (outer_type);
|
||||
|
||||
@ -1147,12 +1158,6 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
|
||||
/* We do not care for const qualification of the pointed-to types
|
||||
as const qualification has no semantic value to the middle-end. */
|
||||
|
||||
/* Do not lose casts to restrict qualified pointers. */
|
||||
if ((TYPE_RESTRICT (outer_type)
|
||||
!= TYPE_RESTRICT (inner_type))
|
||||
&& TYPE_RESTRICT (outer_type))
|
||||
return false;
|
||||
|
||||
/* Otherwise pointers/references are equivalent if their pointed
|
||||
to types are effectively the same. We can strip qualifiers
|
||||
on pointed-to types for further comparison, which is done in
|
||||
|
Loading…
x
Reference in New Issue
Block a user