Handle restrict struct fields recursively 2015-10-26 Tom de Vries * tree-ssa-structalias.c (struct fieldoff): Add restrict_var field. (push_fields_onto_fieldstack): Add and handle handle_param parameter. (create_variable_info_for_1): Add extra arg to call to push_fields_onto_fieldstack. Handle restrict pointer fields. * gcc.dg/tree-ssa/restrict-8.c: New test. --- gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c | 17 ++++++++++++++++ gcc/tree-ssa-structalias.c | 32 +++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c diff --git a/gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c b/gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c new file mode 100644 index 0000000..b0ab164 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/restrict-8.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ + +struct s +{ + int *__restrict__ *__restrict__ pp; +}; + +int +f (struct s s, int *b) +{ + *b = 1; + **s.pp = 2; + return *b; +} + +/* { dg-final { scan-tree-dump-times "return 1" 1 "fre1" } } */ diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index a297a36..fac1739 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -399,6 +399,7 @@ new_var_info (tree t, const char *name) return ret; } +static varinfo_t create_variable_info_for_1 (tree, const char *, bool); /* A map mapping call statements to per-stmt variables for uses and clobbers specific to the call. */ @@ -5196,6 +5197,8 @@ struct fieldoff unsigned may_have_pointers : 1; unsigned only_restrict_pointers : 1; + + varinfo_t restrict_var; }; typedef struct fieldoff fieldoff_s; @@ -5290,11 +5293,12 @@ field_must_have_pointers (tree t) OFFSET is used to keep track of the offset in this entire structure, rather than just the immediately containing structure. Returns false if the caller is supposed to handle the field we - recursed for. */ + recursed for. If HANDLE_PARAM is set, we're handling part of a function + parameter. */ static bool push_fields_onto_fieldstack (tree type, vec *fieldstack, - HOST_WIDE_INT offset) + HOST_WIDE_INT offset, bool handle_param) { tree field; bool empty_p = true; @@ -5320,7 +5324,7 @@ push_fields_onto_fieldstack (tree type, vec *fieldstack, || TREE_CODE (field_type) == UNION_TYPE) push = true; else if (!push_fields_onto_fieldstack - (field_type, fieldstack, offset + foff) + (field_type, fieldstack, offset + foff, handle_param) && (DECL_SIZE (field) && !integer_zerop (DECL_SIZE (field)))) /* Empty structures may have actual size, like in C++. So @@ -5341,7 +5345,8 @@ push_fields_onto_fieldstack (tree type, vec *fieldstack, if (!pair && offset + foff != 0) { - fieldoff_s e = {0, offset + foff, false, false, false, false}; + fieldoff_s e = {0, offset + foff, false, false, false, false, + NULL}; pair = fieldstack->safe_push (e); } @@ -5375,6 +5380,19 @@ push_fields_onto_fieldstack (tree type, vec *fieldstack, = (!has_unknown_size && POINTER_TYPE_P (field_type) && TYPE_RESTRICT (field_type)); + if (handle_param + && e.only_restrict_pointers + && !type_contains_placeholder_p (TREE_TYPE (field_type))) + { + varinfo_t rvi; + tree heapvar = build_fake_var_decl (TREE_TYPE (field_type)); + DECL_EXTERNAL (heapvar) = 1; + rvi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS", + true); + rvi->is_restrict_var = 1; + insert_vi_for_tree (heapvar, rvi); + e.restrict_var = rvi; + } fieldstack->safe_push (e); } } @@ -5679,7 +5697,7 @@ create_variable_info_for_1 (tree decl, const char *name, bool handle_param) bool notokay = false; unsigned int i; - push_fields_onto_fieldstack (decl_type, &fieldstack, 0); + push_fields_onto_fieldstack (decl_type, &fieldstack, 0, handle_param); for (i = 0; !notokay && fieldstack.iterate (i, &fo); i++) if (fo->has_unknown_size @@ -5770,6 +5788,10 @@ create_variable_info_for_1 (tree decl, const char *name, bool handle_param) newvi->fullsize = vi->fullsize; newvi->may_have_pointers = fo->may_have_pointers; newvi->only_restrict_pointers = fo->only_restrict_pointers; + if (handle_param + && newvi->only_restrict_pointers + && fo->restrict_var != NULL) + insert_restrict_pointed_var (newvi, fo->restrict_var); if (i + 1 < fieldstack.length ()) { varinfo_t tem = new_var_info (decl, name); -- 1.9.1