From fb8ed03fa605f7ccb18283a22a90c6cae7a8340c Mon Sep 17 00:00:00 2001 From: rguenth Date: Wed, 5 Nov 2008 12:17:10 +0000 Subject: [PATCH] 2008-11-05 Richard Guenther 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141606 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 14 ++++++++++++ gcc/cp/ChangeLog | 6 +++++ gcc/cp/decl.c | 2 +- gcc/gimplify.c | 2 +- gcc/testsuite/ChangeLog | 7 ++++++ gcc/testsuite/g++.dg/pr37742.C | 10 ++++++++ gcc/testsuite/gcc.c-torture/compile/pr37742.c | 21 +++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c | 6 +++-- gcc/tree-flow.h | 2 ++ gcc/tree-ssa-ccp.c | 33 ++++++++++++++++++++++----- gcc/tree-ssa-forwprop.c | 20 ++++------------ gcc/tree-ssa.c | 19 +++++++++------ 12 files changed, 110 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr37742.C create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr37742.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cade56f..4a6b0c2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2008-11-05 Richard Guenther + + 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 PR middle-end/37286 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 34257e5..3b4f8b1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2008-11-05 Richard Guenther + + PR middle-end/37742 + * decl.c (start_preparsed_function): Use the correct type for + building the RESULT_DECL. + 2008-10-31 Jakub Jelinek PR c++/37967 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 754f433..945b947 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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; diff --git a/gcc/gimplify.c b/gcc/gimplify.c index d2625a7..bec4257 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2522278..79811bd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2008-11-05 Richard Guenther + + 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 PR middle-end/37286 diff --git a/gcc/testsuite/g++.dg/pr37742.C b/gcc/testsuite/g++.dg/pr37742.C new file mode 100644 index 0000000..784eb49 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr37742.C @@ -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(__valarray_get_memory(__n)); +} + diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37742.c b/gcc/testsuite/gcc.c-torture/compile/pr37742.c new file mode 100644 index 0000000..4ef00be --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr37742.c @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c index 6b894b5..0d2bac5 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c @@ -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" } } */ diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index fe649dd..6004978 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -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); diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 0365697..a7d5be3 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -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 diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 7a5233b..a04e7ca 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -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); diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 8f238a3..935cad6 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -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 -- 2.7.4