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
+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
+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
{
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;
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
+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
--- /dev/null
+/* { 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));
+}
+
--- /dev/null
+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;
+}
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" } } */
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);
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.
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
{
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
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);
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);
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);
/* 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