From 2f571334ff457850b9a7748b6af8c8d1d07c8f1c Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Thu, 29 May 2008 10:31:58 +0000 Subject: [PATCH] re PR tree-optimization/36343 (Wrong code due to bad TBAA pruning of points-to-sets and use in call clobbering) 2008-05-29 Richard Guenther PR tree-optimization/36343 PR tree-optimization/36346 PR tree-optimization/36347 * tree-flow.h (clobber_what_p_points_to): Declare. * tree-ssa-structalias.c (set_uids_in_ptset): Whether the pointed-to variable is dereferenced is irrelevant to whether the pointer can access the pointed-to variable. (clobber_what_p_points_to): New function. * tree-ssa-alias.c (set_initial_properties): Use it. * tree-ssa.c (verify_flow_sensitive_alias_info): Adjust call clobber check for NMTs. * gcc.c-torture/execute/pr36343.c: New testcase. From-SVN: r136152 --- gcc/ChangeLog | 14 ++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.c-torture/execute/pr36343.c | 32 ++++++++ gcc/tree-flow.h | 1 + gcc/tree-ssa-alias.c | 35 ++++----- gcc/tree-ssa-structalias.c | 76 +++++++++++++++++-- gcc/tree-ssa.c | 4 +- 7 files changed, 141 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr36343.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9c10b88973f..72477652d6d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2008-05-29 Richard Guenther + + PR tree-optimization/36343 + PR tree-optimization/36346 + PR tree-optimization/36347 + * tree-flow.h (clobber_what_p_points_to): Declare. + * tree-ssa-structalias.c (set_uids_in_ptset): Whether the + pointed-to variable is dereferenced is irrelevant to whether + the pointer can access the pointed-to variable. + (clobber_what_p_points_to): New function. + * tree-ssa-alias.c (set_initial_properties): Use it. + * tree-ssa.c (verify_flow_sensitive_alias_info): Adjust + call clobber check for NMTs. + 2008-05-28 Seongbae Park * value-prof.c (tree_ic_transform): Use HOST_WIDEST_INT_PRINT_DEC diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f52843acc82..9f77f70634b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-05-29 Richard Guenther + + PR tree-optimization/36343 + * gcc.c-torture/execute/pr36343.c: New testcase. + 2008-05-29 Arnaud Charlet * gnat.dg/abstract1.ad[sb]: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr36343.c b/gcc/testsuite/gcc.c-torture/execute/pr36343.c new file mode 100644 index 00000000000..44b9fb34075 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr36343.c @@ -0,0 +1,32 @@ +extern void abort (void); + +void __attribute__((noinline)) +bar (int **p) +{ + float *q = (float *)p; + *q = 0.0; +} + +float __attribute__((noinline)) +foo (int b) +{ + int *i = 0; + float f = 1.0; + int **p; + if (b) + p = &i; + else + p = (int **)&f; + bar (p); + if (b) + return **p; + return f; +} + +int main() +{ + if (foo(0) != 0.0) + abort (); + return 0; +} + diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 8bc6cc8a0ca..94d5a69f69c 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -1167,6 +1167,7 @@ tree gimple_fold_indirect_ref (tree); /* In tree-ssa-structalias.c */ bool find_what_p_points_to (tree); +bool clobber_what_p_points_to (tree); /* In tree-ssa-live.c */ extern void remove_unused_locals (void); diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 4f661543a55..1523aebac17 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -545,8 +545,14 @@ set_initial_properties (struct alias_info *ai) { struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr); tree tag = symbol_mem_tag (SSA_NAME_VAR (ptr)); - - if (pi->value_escapes_p) + + /* A pointer that only escapes via a function return does not + add to the call clobber or call used solution. + To exclude ESCAPE_TO_PURE_CONST we would need to track + call used variables separately or compute those properly + in the operand scanner. */ + if (pi->value_escapes_p + && pi->escape_mask & ~ESCAPE_TO_RETURN) { /* If PTR escapes then its associated memory tags and pointed-to variables are call-clobbered. */ @@ -556,24 +562,13 @@ set_initial_properties (struct alias_info *ai) if (tag) mark_call_clobbered (tag, pi->escape_mask); - if (pi->pt_vars) - { - bitmap_iterator bi; - unsigned int j; - EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi) - { - tree alias = referenced_var (j); - - /* If you clobber one part of a structure, you - clobber the entire thing. While this does not make - the world a particularly nice place, it is necessary - in order to allow C/C++ tricks that involve - pointer arithmetic to work. */ - if (!unmodifiable_var_p (alias)) - mark_call_clobbered (alias, pi->escape_mask); - } - } - else if (pi->pt_anything) + /* Defer to points-to analysis if possible, otherwise + clobber all addressable variables. Parameters cannot + point to local memory though. + ??? Properly tracking which pointers point to non-local + memory only would make a big difference here. */ + if (!clobber_what_p_points_to (ptr) + && !(pi->escape_mask & ESCAPE_IS_PARM)) { any_pt_anything = true; pt_anything_mask |= pi->escape_mask; diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 7c79a3df68d..b6d73ce66f4 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -4664,17 +4664,19 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed, || TREE_CODE (vi->decl) == RESULT_DECL) { /* Just add VI->DECL to the alias set. - Don't type prune artificial vars. */ - if (vi->is_artificial_var) + Don't type prune artificial vars or points-to sets + for pointers that have not been dereferenced or with + type-based pruning disabled. */ + if (vi->is_artificial_var + || !is_derefed + || no_tbaa_pruning) bitmap_set_bit (into, DECL_UID (vi->decl)); else { alias_set_type var_alias_set, ptr_alias_set; var_alias_set = get_alias_set (vi->decl); ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr))); - if (no_tbaa_pruning - || (!is_derefed && !vi->directly_dereferenced) - || alias_sets_conflict_p (ptr_alias_set, var_alias_set)) + if (alias_sets_conflict_p (ptr_alias_set, var_alias_set)) bitmap_set_bit (into, DECL_UID (vi->decl)); } } @@ -4885,7 +4887,71 @@ find_what_p_points_to (tree p) return false; } +/* Mark everything that p points to as call clobbered. Returns true + if everything is done and false if all addressable variables need to + be clobbered because p points to anything. */ +bool +clobber_what_p_points_to (tree p) +{ + tree lookup_p = p; + varinfo_t vi; + struct ptr_info_def *pi; + unsigned int i; + bitmap_iterator bi; + + if (!have_alias_info) + return false; + + /* For parameters, get at the points-to set for the actual parm + decl. */ + if (TREE_CODE (p) == SSA_NAME + && TREE_CODE (SSA_NAME_VAR (p)) == PARM_DECL + && SSA_NAME_IS_DEFAULT_DEF (p)) + lookup_p = SSA_NAME_VAR (p); + + vi = lookup_vi_for_tree (lookup_p); + if (!vi) + return false; + + /* We are asking for the points-to solution of pointers. */ + gcc_assert (!vi->is_artificial_var + && vi->size == vi->fullsize); + + pi = get_ptr_info (p); + + /* This variable may have been collapsed, let's get the real + variable. */ + vi = get_varinfo (find (vi->id)); + + /* Mark variables in the solution call-clobbered. */ + EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, i, bi) + { + varinfo_t vi = get_varinfo (i); + + if (vi->is_artificial_var) + { + /* nothing_id and readonly_id do not cause any + call clobber ops. For anything_id and integer_id + we need to clobber all addressable vars. */ + if (vi->id == anything_id + || vi->id == integer_id) + return false; + } + + /* Only artificial heap-vars are further interesting. */ + if (vi->is_artificial_var && !vi->is_heap_var) + continue; + + if ((TREE_CODE (vi->decl) == VAR_DECL + || TREE_CODE (vi->decl) == PARM_DECL + || TREE_CODE (vi->decl) == RESULT_DECL) + && !unmodifiable_var_p (vi->decl)) + mark_call_clobbered (vi->decl, pi->escape_mask); + } + + return true; +} /* Dump points-to information to OUTFILE. */ diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 1c01d71bf6e..f71e3af7ff9 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -571,7 +571,9 @@ verify_flow_sensitive_alias_info (void) goto err; } - if (pi->value_escapes_p && pi->name_mem_tag) + if (pi->value_escapes_p + && pi->escape_mask & ~ESCAPE_TO_RETURN + && pi->name_mem_tag) { tree t = memory_partition (pi->name_mem_tag); if (t == NULL_TREE) -- 2.30.2