Hi! CAST_RESTRICT based disambiguation unfortunately isn't reliable, e.g. to store a non-restrict pointer into a restricted field, we add a non-useless cast to restricted pointer in the gimplifier, and while we don't consider that field to have a special restrict tag because it is unsafe to do so, we unfortunately create it for the CAST_RESTRICT before that and end up with different restrict tags for the same thing. See the PR for more details.
This patch turns off CAST_RESTRICT handling for now, in the future we might try to replace it by explicit CAST_RESTRICT stmts in some form, but need to solve problems with multiple inlined copies of the same function with restrict arguments or restrict variables in it and intermixed code from them (or similarly code from different non-overlapping source blocks). Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 4.6 too? 2011-10-06 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/49279 * tree-ssa-structalias.c (find_func_aliases): Don't handle CAST_RESTRICT. * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Allow restrict propagation. * tree-ssa.c (useless_type_conversion_p): Don't return false if TYPE_RESTRICT differs. * gcc.dg/tree-ssa/restrict-4.c: XFAIL. * gcc.c-torture/execute/pr49279.c: New test. --- gcc/tree-ssa-structalias.c.jj 2011-10-04 10:18:29.000000000 +0200 +++ gcc/tree-ssa-structalias.c 2011-10-05 12:43:42.000000000 +0200 @@ -4494,15 +4494,6 @@ find_func_aliases (gimple origt) && (!in_ipa_mode || DECL_EXTERNAL (lhsop) || TREE_PUBLIC (lhsop))) make_escape_constraint (rhsop); - /* If this is a conversion of a non-restrict pointer to a - restrict pointer track it with a new heapvar. */ - else if (gimple_assign_cast_p (t) - && POINTER_TYPE_P (TREE_TYPE (rhsop)) - && POINTER_TYPE_P (TREE_TYPE (lhsop)) - && !TYPE_RESTRICT (TREE_TYPE (rhsop)) - && TYPE_RESTRICT (TREE_TYPE (lhsop))) - make_constraint_from_restrict (get_vi_for_tree (lhsop), - "CAST_RESTRICT"); } /* Handle escapes through return. */ else if (gimple_code (t) == GIMPLE_RETURN --- gcc/tree-ssa-forwprop.c.jj 2011-10-04 14:36:00.000000000 +0200 +++ gcc/tree-ssa-forwprop.c 2011-10-05 12:46:32.000000000 +0200 @@ -804,11 +804,6 @@ forward_propagate_addr_expr_1 (tree name && ((rhs_code == SSA_NAME && rhs == name) || CONVERT_EXPR_CODE_P (rhs_code))) { - /* Don't propagate restrict pointer's RHS. */ - if (TYPE_RESTRICT (TREE_TYPE (lhs)) - && !TYPE_RESTRICT (TREE_TYPE (name)) - && !is_gimple_min_invariant (def_rhs)) - return false; /* Only recurse if we don't deal with a single use or we cannot do the propagation to the current statement. In particular we can end up with a conversion needed for a non-invariant --- gcc/tree-ssa.c.jj 2011-09-15 12:18:54.000000000 +0200 +++ gcc/tree-ssa.c 2011-10-05 12:44:52.000000000 +0200 @@ -1270,12 +1270,6 @@ useless_type_conversion_p (tree outer_ty != TYPE_ADDR_SPACE (TREE_TYPE (inner_type))) return false; - /* Do not lose casts to restrict qualified pointers. */ - if ((TYPE_RESTRICT (outer_type) - != TYPE_RESTRICT (inner_type)) - && TYPE_RESTRICT (outer_type)) - return false; - /* If the outer type is (void *), the conversion is not necessary. */ if (VOID_TYPE_P (TREE_TYPE (outer_type))) return true; --- gcc/testsuite/gcc.dg/tree-ssa/restrict-4.c.jj 2011-10-04 14:33:08.000000000 +0200 +++ gcc/testsuite/gcc.dg/tree-ssa/restrict-4.c 2011-10-05 16:22:33.232433231 +0200 @@ -22,5 +22,5 @@ bar (int *x, int y) return p1[y]; } -/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" { xfail *-*-* } } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ --- gcc/testsuite/gcc.c-torture/execute/pr49279.c.jj 2011-10-05 13:32:43.087670846 +0200 +++ gcc/testsuite/gcc.c-torture/execute/pr49279.c 2011-10-05 13:32:43.087670846 +0200 @@ -0,0 +1,35 @@ +/* PR tree-optimization/49279 */ +extern void abort (void); + +struct S { int a; int *__restrict p; }; + +__attribute__((noinline, noclone)) +struct S *bar (struct S *p) +{ + struct S *r; + asm volatile ("" : "=r" (r) : "0" (p) : "memory"); + return r; +} + +__attribute__((noinline, noclone)) +int +foo (int *p, int *q) +{ + struct S s, *t; + s.a = 1; + s.p = p; + t = bar (&s); + t->p = q; + s.p[0] = 0; + t->p[0] = 1; + return s.p[0]; +} + +int +main () +{ + int a, b; + if (foo (&a, &b) != 1) + abort (); + return 0; +} Jakub