aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-06-29 12:23:21 +0000
committerRichard Guenther <rguenther@suse.de>2009-06-29 12:23:21 +0000
commitef1b92b16a19055ee9813fb2ddd921a929c45c04 (patch)
tree9628cef93c202d8f6bd22c558673343fbd31f01a
parente1bc25ea49c99ba542b4d8e99af3dbcc5a4a8c26 (diff)
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: https://gcc.gnu.org/svn/gcc/trunk@149048 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20090623-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c27
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/restrict-1.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/restrict-2.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c18
-rw-r--r--gcc/tree-ssa-alias.c7
-rw-r--r--gcc/tree-ssa-alias.h5
-rw-r--r--gcc/tree-ssa-structalias.c297
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. */