diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-06-29 12:23:21 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-06-29 12:23:21 +0000 |
commit | 1c1f1bc0ab7e9b35d4dd92a983a0c72ba215cb2d (patch) | |
tree | 9628cef93c202d8f6bd22c558673343fbd31f01a | |
parent | 8115f0afdaff380da01d555b0584cd0fceb789b8 (diff) | |
download | gcc-1c1f1bc0ab7e9b35d4dd92a983a0c72ba215cb2d.tar.gz |
2009-06-29 Richard Guenther <rguenther@suse.de>
PR middle-end/14187
* tree-ssa-alias.h (struct pt_solution): Add vars_contains_restrict
flag.
(pt_solutions_same_restrict_base): Declare.
* tree-ssa-structalias.c (struct variable_info): Add is_restrict_var
flag.
(new_var_info): Initialize is_global_var properly for SSA_NAMEs.
(make_constraint_from, make_copy_constraint): Move earlier.
(make_constraint_from_heapvar): New function.
(make_constraint_from_restrict): Likewise.
(handle_lhs_call): Use it.
(find_func_aliases): Use it to track conversions to restrict
qualified pointers.
(struct fieldoff): Add only_restrict_pointers flag.
(push_fields_onto_fieldstack): Initialize it.
(create_variable_info_for): Track global restrict qualified pointers.
(intra_create_variable_infos): Use make_constraint_from_heapvar.
Track restrict qualified pointer arguments.
(set_uids_in_ptset): Use varinfo is_global_var flag.
(find_what_var_points_to): Set the vars_contains_restrict flag.
Always create the points-to solution for sets including restrict tags.
(pt_solutions_same_restrict_base): New function.
* tree-ssa-alias.c (ptr_derefs_may_alias_p): For two restrict
qualified pointers use pt_solutions_same_restrict_base as
additional source for disambiguation.
* gcc.dg/tree-ssa/restrict-1.c: New testcase.
* gcc.dg/tree-ssa/restrict-2.c: Likewise.
* gcc.dg/tree-ssa/restrict-3.c: Likewise.
* gcc.c-torture/execute/20090623-1.c: Likewise.
* gcc.dg/tree-ssa/ldist-13.c: Likewise.
* gcc.dg/tree-ssa/ldist-14.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@149048 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 28 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20090623-1.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/restrict-1.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/restrict-2.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c | 18 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 7 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.h | 5 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 297 |
11 files changed, 344 insertions, 122 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3066cbe65f8..351175cfaab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,33 @@ 2009-06-29 Richard Guenther <rguenther@suse.de> + PR middle-end/14187 + * tree-ssa-alias.h (struct pt_solution): Add vars_contains_restrict + flag. + (pt_solutions_same_restrict_base): Declare. + * tree-ssa-structalias.c (struct variable_info): Add is_restrict_var + flag. + (new_var_info): Initialize is_global_var properly for SSA_NAMEs. + (make_constraint_from, make_copy_constraint): Move earlier. + (make_constraint_from_heapvar): New function. + (make_constraint_from_restrict): Likewise. + (handle_lhs_call): Use it. + (find_func_aliases): Use it to track conversions to restrict + qualified pointers. + (struct fieldoff): Add only_restrict_pointers flag. + (push_fields_onto_fieldstack): Initialize it. + (create_variable_info_for): Track global restrict qualified pointers. + (intra_create_variable_infos): Use make_constraint_from_heapvar. + Track restrict qualified pointer arguments. + (set_uids_in_ptset): Use varinfo is_global_var flag. + (find_what_var_points_to): Set the vars_contains_restrict flag. + Always create the points-to solution for sets including restrict tags. + (pt_solutions_same_restrict_base): New function. + * tree-ssa-alias.c (ptr_derefs_may_alias_p): For two restrict + qualified pointers use pt_solutions_same_restrict_base as + additional source for disambiguation. + +2009-06-29 Richard Guenther <rguenther@suse.de> + PR middle-end/38212 * alias.c (find_base_decl): Remove. (get_deref_alias_set_1): Remove restrict handling. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dbac55fdf80..d325d4ab0a6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,15 @@ 2009-06-29 Richard Guenther <rguenther@suse.de> + PR middle-end/14187 + * gcc.dg/tree-ssa/restrict-1.c: New testcase. + * gcc.dg/tree-ssa/restrict-2.c: Likewise. + * gcc.dg/tree-ssa/restrict-3.c: Likewise. + * gcc.c-torture/execute/20090623-1.c: Likewise. + * gcc.dg/tree-ssa/ldist-13.c: Likewise. + * gcc.dg/tree-ssa/ldist-14.c: Likewise. + +2009-06-29 Richard Guenther <rguenther@suse.de> + PR middle-end/38212 * gcc.c-torture/execute/pr38212.c: New testcase. diff --git a/gcc/testsuite/gcc.c-torture/execute/20090623-1.c b/gcc/testsuite/gcc.c-torture/execute/20090623-1.c new file mode 100644 index 00000000000..09a5672cd74 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20090623-1.c @@ -0,0 +1,18 @@ +int * __restrict__ x; + +int foo (int y) +{ + *x = y; + return *x; +} + +extern void abort (void); + +int main() +{ + int i = 0; + x = &i; + if (foo(1) != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c new file mode 100644 index 00000000000..9841569543e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */ + +float * __restrict__ x; +float * __restrict__ y; + +float foo (int n) +{ + int i; + float tmp = 0.0; + for (i = 0; i < n; ++i) + { + x[i] = 0.0; + tmp += y[i]; + } + return tmp; +} + +/* We should apply loop distribution. */ + +/* { dg-final { scan-tree-dump "Loop 1 distributed: split to 2 loops" "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c new file mode 100644 index 00000000000..700599f1ccb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-strict-aliasing -ftree-loop-distribution -fdump-tree-ldist-details" } */ + +struct desc { + int i; + void * __restrict__ data; + int j; +} a, b; + +float foo (int n) +{ + int i; + float * __restrict__ x, * __restrict__ y, tmp = 0.0; + x = (float * __restrict__)a.data; + y = (float * __restrict__)b.data; + for (i = 0; i < n; ++i) + { + x[i] = 0.0; + tmp += y[i]; + } + return tmp; +} + +/* We should apply loop distribution. */ + +/* { dg-final { scan-tree-dump "Loop 1 distributed: split to 2 loops" "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/restrict-1.c b/gcc/testsuite/gcc.dg/tree-ssa/restrict-1.c new file mode 100644 index 00000000000..08fc10f5609 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/restrict-1.c @@ -0,0 +1,20 @@ +/* { dg-do link } */ +/* { dg-options "-O -fno-strict-aliasing -fdump-tree-optimized" } */ + +extern void link_error (void); + +void bar0 (int * __restrict__ arr1, int * __restrict__ arr2) +{ + arr1[0] = 1; + arr2[0] = 1; + if (arr1[0] != 1) + link_error (); +} + +int main() +{ + return 0; +} + +/* { dg-final { scan-tree-dump-not "link_error" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/restrict-2.c b/gcc/testsuite/gcc.dg/tree-ssa/restrict-2.c new file mode 100644 index 00000000000..b76ad98fa88 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/restrict-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-strict-aliasing -fdump-tree-lim-details" } */ + +void foo (float * __restrict__ a, float * __restrict__ b, int n, int j) +{ + int i; + for(i = 0; i < n; ++i) + a[i] = (b[j+50] + b[j-50]) * 0.5f; +} + +/* We should move the RHS of the store out of the loop. */ + +/* { dg-final { scan-tree-dump-times "Moving statement" 11 "lim" } } */ +/* { dg-final { cleanup-tree-dump "lim" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c b/gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c new file mode 100644 index 00000000000..08faafada25 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-strict-aliasing -fdump-tree-lim-details" } */ + +void f(int * __restrict__ r, + int a[__restrict__ 16][16], + int b[__restrict__ 16][16], + int i, int j) +{ + int x; + *r = 0; + for (x = 1; x < 16; ++x) + *r = *r + a[i][x] * b[x][j]; +} + +/* We should apply store motion to the store to *r. */ + +/* { dg-final { scan-tree-dump "Executing store motion of \\\*r" "lim" } } */ +/* { dg-final { cleanup-tree-dump "lim" } } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 14733675262..e8bca84ba35 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -273,6 +273,13 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2) if (!pi1 || !pi2) return true; + /* If both pointers are restrict-qualified try to disambiguate + with restrict information. */ + if (TYPE_RESTRICT (TREE_TYPE (ptr1)) + && TYPE_RESTRICT (TREE_TYPE (ptr2)) + && !pt_solutions_same_restrict_base (&pi1->pt, &pi2->pt)) + return false; + /* ??? This does not use TBAA to prune decls from the intersection that not both pointers may access. */ return pt_solutions_intersect (&pi1->pt, &pi2->pt); diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h index 9115e61c22c..b071e4b1b81 100644 --- a/gcc/tree-ssa-alias.h +++ b/gcc/tree-ssa-alias.h @@ -49,6 +49,9 @@ struct GTY(()) pt_solution /* Nonzero if the pt_vars bitmap includes a global variable. */ unsigned int vars_contains_global : 1; + /* Nonzero if the pt_vars bitmap includes a restrict tag variable. */ + unsigned int vars_contains_restrict : 1; + /* Set of variables that this pointer may point to. */ bitmap vars; }; @@ -115,6 +118,8 @@ extern void delete_alias_heapvars (void); extern bool pt_solution_includes_global (struct pt_solution *); extern bool pt_solution_includes (struct pt_solution *, const_tree); extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *); +extern bool pt_solutions_same_restrict_base (struct pt_solution *, + struct pt_solution *); extern void pt_solution_reset (struct pt_solution *); extern void dump_pta_stats (FILE *); diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index b175391c374..ad5482aa4ae 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -211,20 +211,23 @@ struct variable_info /* True if this is a variable created by the constraint analysis, such as heap variables and constraints we had to break up. */ - unsigned int is_artificial_var:1; + unsigned int is_artificial_var : 1; /* True if this is a special variable whose solution set should not be changed. */ - unsigned int is_special_var:1; + unsigned int is_special_var : 1; /* True for variables whose size is not known or variable. */ - unsigned int is_unknown_size_var:1; + unsigned int is_unknown_size_var : 1; /* True for (sub-)fields that represent a whole variable. */ unsigned int is_full_var : 1; /* True if this is a heap variable. */ - unsigned int is_heap_var:1; + unsigned int is_heap_var : 1; + + /* True if this is a variable tracking a restrict pointer source. */ + unsigned int is_restrict_var : 1; /* True if this field may contain pointers. */ unsigned int may_have_pointers : 1; @@ -339,7 +342,7 @@ new_var_info (tree t, const char *name) ret->is_special_var = false; ret->is_unknown_size_var = false; ret->may_have_pointers = true; - ret->is_global_var = true; + ret->is_global_var = (t == NULL_TREE); if (t && DECL_P (t)) ret->is_global_var = is_global_var (t); ret->solution = BITMAP_ALLOC (&pta_obstack); @@ -3312,6 +3315,40 @@ make_constraint_to (unsigned id, tree op) VEC_free (ce_s, heap, rhsc); } +/* Create a constraint ID = &FROM. */ + +static void +make_constraint_from (varinfo_t vi, int from) +{ + struct constraint_expr lhs, rhs; + + lhs.var = vi->id; + lhs.offset = 0; + lhs.type = SCALAR; + + rhs.var = from; + rhs.offset = 0; + rhs.type = ADDRESSOF; + process_constraint (new_constraint (lhs, rhs)); +} + +/* Create a constraint ID = FROM. */ + +static void +make_copy_constraint (varinfo_t vi, int from) +{ + struct constraint_expr lhs, rhs; + + lhs.var = vi->id; + lhs.offset = 0; + lhs.type = SCALAR; + + rhs.var = from; + rhs.offset = 0; + rhs.type = SCALAR; + process_constraint (new_constraint (lhs, rhs)); +} + /* Make constraints necessary to make OP escape. */ static void @@ -3320,6 +3357,61 @@ make_escape_constraint (tree op) make_constraint_to (escaped_id, op); } +/* Create a new artificial heap variable with NAME and make a + constraint from it to LHS. Return the created variable. */ + +static varinfo_t +make_constraint_from_heapvar (varinfo_t lhs, const char *name) +{ + varinfo_t vi; + tree heapvar = heapvar_lookup (lhs->decl); + + if (heapvar == NULL_TREE) + { + var_ann_t ann; + heapvar = create_tmp_var_raw (ptr_type_node, name); + DECL_EXTERNAL (heapvar) = 1; + + heapvar_insert (lhs->decl, heapvar); + + ann = get_var_ann (heapvar); + ann->is_heapvar = 1; + } + + /* For global vars we need to add a heapvar to the list of referenced + vars of a different function than it was created for originally. */ + if (gimple_referenced_vars (cfun)) + add_referenced_var (heapvar); + + vi = new_var_info (heapvar, name); + vi->is_artificial_var = true; + vi->is_heap_var = true; + vi->is_unknown_size_var = true; + vi->fullsize = ~0; + vi->size = ~0; + vi->is_full_var = true; + insert_vi_for_tree (heapvar, vi); + + make_constraint_from (lhs, vi->id); + + return vi; +} + +/* Create a new artificial heap variable with NAME and make a + constraint from it to LHS. Set flags according to a tag used + for tracking restrict pointers. */ + +static void +make_constraint_from_restrict (varinfo_t lhs, const char *name) +{ + varinfo_t vi; + vi = make_constraint_from_heapvar (lhs, name); + vi->is_restrict_var = 1; + vi->is_global_var = 0; + vi->is_special_var = 1; + vi->may_have_pointers = 0; +} + /* For non-IPA mode, generate constraints necessary for a call on the RHS. */ @@ -3374,39 +3466,14 @@ static void handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc) { VEC(ce_s, heap) *lhsc = NULL; - unsigned int j; - struct constraint_expr *lhsp; get_constraint_for (lhs, &lhsc); if (flags & ECF_MALLOC) { - struct constraint_expr rhsc; - tree heapvar = heapvar_lookup (lhs); varinfo_t vi; - - if (heapvar == NULL) - { - heapvar = create_tmp_var_raw (ptr_type_node, "HEAP"); - DECL_EXTERNAL (heapvar) = 1; - get_var_ann (heapvar)->is_heapvar = 1; - if (gimple_referenced_vars (cfun)) - add_referenced_var (heapvar); - heapvar_insert (lhs, heapvar); - } - - rhsc.var = create_variable_info_for (heapvar, - alias_get_name (heapvar)); - vi = get_varinfo (rhsc.var); - vi->is_artificial_var = 1; - vi->is_heap_var = 1; - vi->is_unknown_size_var = true; - vi->fullsize = ~0; - vi->size = ~0; - rhsc.type = ADDRESSOF; - rhsc.offset = 0; - for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++) - process_constraint (new_constraint (*lhsp, rhsc)); + vi = make_constraint_from_heapvar (get_vi_for_tree (lhs), "HEAP"); + make_copy_constraint (vi, nonlocal_id); } else if (VEC_length (ce_s, rhsc) > 0) { @@ -3826,6 +3893,15 @@ find_func_aliases (gimple origt) && DECL_P (lhsop) && is_global_var (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"); } /* For conversions of pointers to non-pointers the pointer escapes. */ else if (gimple_assign_cast_p (t) @@ -4017,6 +4093,8 @@ struct fieldoff unsigned has_unknown_size : 1; unsigned may_have_pointers : 1; + + unsigned only_restrict_pointers : 1; }; typedef struct fieldoff fieldoff_s; @@ -4155,6 +4233,10 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, else pair->size = -1; pair->may_have_pointers = could_have_pointers (field); + pair->only_restrict_pointers + = (!has_unknown_size + && POINTER_TYPE_P (TREE_TYPE (field)) + && TYPE_RESTRICT (TREE_TYPE (field))); count++; } } @@ -4165,40 +4247,6 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, return count; } -/* Create a constraint ID = &FROM. */ - -static void -make_constraint_from (varinfo_t vi, int from) -{ - struct constraint_expr lhs, rhs; - - lhs.var = vi->id; - lhs.offset = 0; - lhs.type = SCALAR; - - rhs.var = from; - rhs.offset = 0; - rhs.type = ADDRESSOF; - process_constraint (new_constraint (lhs, rhs)); -} - -/* Create a constraint ID = FROM. */ - -static void -make_copy_constraint (varinfo_t vi, int from) -{ - struct constraint_expr lhs, rhs; - - lhs.var = vi->id; - lhs.offset = 0; - lhs.type = SCALAR; - - rhs.var = from; - rhs.offset = 0; - rhs.type = SCALAR; - process_constraint (new_constraint (lhs, rhs)); -} - /* Count the number of arguments DECL has, and set IS_VARARGS to true if it is a varargs function. */ @@ -4346,17 +4394,12 @@ create_variable_info_for (tree decl, const char *name) varinfo_t vi; tree decl_type = TREE_TYPE (decl); tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decl_type); - bool is_global = DECL_P (decl) ? is_global_var (decl) : false; VEC (fieldoff_s,heap) *fieldstack = NULL; if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode) return create_function_info_for (decl, name); - if (var_can_have_subvars (decl) && use_field_sensitive - && (!var_ann (decl) - || var_ann (decl)->noalias_state == 0) - && (!var_ann (decl) - || !var_ann (decl)->is_heapvar)) + if (var_can_have_subvars (decl) && use_field_sensitive) push_fields_onto_fieldstack (decl_type, &fieldstack, 0); /* If the variable doesn't have subvars, we may end up needing to @@ -4379,14 +4422,14 @@ create_variable_info_for (tree decl, const char *name) } insert_vi_for_tree (vi->decl, vi); - if (is_global && (!flag_whole_program || !in_ipa_mode) + if (vi->is_global_var + && (!flag_whole_program || !in_ipa_mode) && vi->may_have_pointers) { - if (var_ann (decl) - && var_ann (decl)->noalias_state == NO_ALIAS_ANYTHING) - make_constraint_from (vi, vi->id); - else - make_copy_constraint (vi, nonlocal_id); + if (POINTER_TYPE_P (TREE_TYPE (decl)) + && TYPE_RESTRICT (TREE_TYPE (decl))) + make_constraint_from_restrict (vi, "GLOBAL_RESTRICT"); + make_copy_constraint (vi, nonlocal_id); } stats.total_vars++; @@ -4463,9 +4506,14 @@ create_variable_info_for (tree decl, const char *name) newvi->fullsize = vi->fullsize; newvi->may_have_pointers = fo->may_have_pointers; insert_into_field_list (vi, newvi); - if (is_global && (!flag_whole_program || !in_ipa_mode) + if (newvi->is_global_var + && (!flag_whole_program || !in_ipa_mode) && newvi->may_have_pointers) - make_copy_constraint (newvi, nonlocal_id); + { + if (fo->only_restrict_pointers) + make_constraint_from_restrict (newvi, "GLOBAL_RESTRICT"); + make_copy_constraint (newvi, nonlocal_id); + } stats.total_vars++; } @@ -4518,7 +4566,6 @@ static void intra_create_variable_infos (void) { tree t; - struct constraint_expr lhs, rhs; /* For each incoming pointer argument arg, create the constraint ARG = NONLOCAL or a dummy variable if flag_argument_noalias is set. */ @@ -4536,50 +4583,28 @@ intra_create_variable_infos (void) if (POINTER_TYPE_P (TREE_TYPE (t)) && flag_argument_noalias > 0) { varinfo_t vi; - tree heapvar = heapvar_lookup (t); - - lhs.offset = 0; - lhs.type = SCALAR; - lhs.var = get_vi_for_tree (t)->id; + var_ann_t ann; - if (heapvar == NULL_TREE) + vi = make_constraint_from_heapvar (get_vi_for_tree (t), + "PARM_NOALIAS"); + ann = get_var_ann (vi->decl); + if (flag_argument_noalias == 1) { - var_ann_t ann; - heapvar = create_tmp_var_raw (ptr_type_node, - "PARM_NOALIAS"); - DECL_EXTERNAL (heapvar) = 1; - if (gimple_referenced_vars (cfun)) - add_referenced_var (heapvar); - - heapvar_insert (t, heapvar); - - ann = get_var_ann (heapvar); - ann->is_heapvar = 1; - if (flag_argument_noalias == 1) - ann->noalias_state = NO_ALIAS; - else if (flag_argument_noalias == 2) - ann->noalias_state = NO_ALIAS_GLOBAL; - else if (flag_argument_noalias == 3) - ann->noalias_state = NO_ALIAS_ANYTHING; - else - gcc_unreachable (); + ann->noalias_state = NO_ALIAS; + make_copy_constraint (vi, nonlocal_id); } - - vi = get_vi_for_tree (heapvar); - vi->is_artificial_var = 1; - vi->is_heap_var = 1; - vi->is_unknown_size_var = true; - vi->fullsize = ~0; - vi->size = ~0; - rhs.var = vi->id; - rhs.type = ADDRESSOF; - rhs.offset = 0; - for (p = get_varinfo (lhs.var); p; p = p->next) + else if (flag_argument_noalias == 2) + { + ann->noalias_state = NO_ALIAS_GLOBAL; + make_constraint_from (vi, vi->id); + } + else if (flag_argument_noalias == 3) { - struct constraint_expr temp = lhs; - temp.var = p->id; - process_constraint (new_constraint (temp, rhs)); + ann->noalias_state = NO_ALIAS_ANYTHING; + make_constraint_from (vi, vi->id); } + else + gcc_unreachable (); } else { @@ -4588,6 +4613,9 @@ intra_create_variable_infos (void) for (p = arg_vi; p; p = p->next) make_constraint_from (p, nonlocal_id); } + if (POINTER_TYPE_P (TREE_TYPE (t)) + && TYPE_RESTRICT (TREE_TYPE (t))) + make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT"); } /* Add a constraint for a result decl that is passed by reference. */ @@ -4704,7 +4732,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt) /* Add the decl to the points-to set. Note that the points-to set contains global variables. */ bitmap_set_bit (into, DECL_UID (vi->decl)); - if (is_global_var (vi->decl)) + if (vi->is_global_var) pt->vars_contains_global = true; } } @@ -4753,11 +4781,15 @@ find_what_var_points_to (varinfo_t vi, struct pt_solution *pt) || vi->id == integer_id) pt->anything = 1; } + if (vi->is_restrict_var) + pt->vars_contains_restrict = true; } /* Instead of doing extra work, simply do not create elaborate points-to information for pt_anything pointers. */ - if (pt->anything) + if (pt->anything + && (vi->is_artificial_var + || !pt->vars_contains_restrict)) return; /* Share the final set of variables when possible. */ @@ -4967,6 +4999,27 @@ pt_solutions_intersect (struct pt_solution *pt1, struct pt_solution *pt2) return res; } +/* Return true if both points-to solutions PT1 and PT2 for two restrict + qualified pointers are possibly based on the same pointer. */ + +bool +pt_solutions_same_restrict_base (struct pt_solution *pt1, + struct pt_solution *pt2) +{ + /* If we deal with points-to solutions of two restrict qualified + pointers solely rely on the pointed-to variable bitmap intersection. + For two pointers that are based on each other the bitmaps will + intersect. */ + if (pt1->vars_contains_restrict + && pt2->vars_contains_restrict) + { + gcc_assert (pt1->vars && pt2->vars); + return bitmap_intersect_p (pt1->vars, pt2->vars); + } + + return true; +} + /* Dump points-to information to OUTFILE. */ |