Commit 2f571334 by Richard Guenther Committed by Richard Biener

re PR tree-optimization/36343 (Wrong code due to bad TBAA pruning of…

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  <rguenther@suse.de>

	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
parent b3d5f741
2008-05-29 Richard Guenther <rguenther@suse.de>
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 <seongbae.park@gmail.com> 2008-05-28 Seongbae Park <seongbae.park@gmail.com>
* value-prof.c (tree_ic_transform): Use HOST_WIDEST_INT_PRINT_DEC * value-prof.c (tree_ic_transform): Use HOST_WIDEST_INT_PRINT_DEC
......
2008-05-29 Richard Guenther <rguenther@suse.de>
PR tree-optimization/36343
* gcc.c-torture/execute/pr36343.c: New testcase.
2008-05-29 Arnaud Charlet <charlet@adacore.com> 2008-05-29 Arnaud Charlet <charlet@adacore.com>
* gnat.dg/abstract1.ad[sb]: New test. * gnat.dg/abstract1.ad[sb]: New test.
......
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;
}
...@@ -1167,6 +1167,7 @@ tree gimple_fold_indirect_ref (tree); ...@@ -1167,6 +1167,7 @@ tree gimple_fold_indirect_ref (tree);
/* In tree-ssa-structalias.c */ /* In tree-ssa-structalias.c */
bool find_what_p_points_to (tree); bool find_what_p_points_to (tree);
bool clobber_what_p_points_to (tree);
/* In tree-ssa-live.c */ /* In tree-ssa-live.c */
extern void remove_unused_locals (void); extern void remove_unused_locals (void);
......
...@@ -545,8 +545,14 @@ set_initial_properties (struct alias_info *ai) ...@@ -545,8 +545,14 @@ set_initial_properties (struct alias_info *ai)
{ {
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr); struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
tree tag = symbol_mem_tag (SSA_NAME_VAR (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 /* If PTR escapes then its associated memory tags and
pointed-to variables are call-clobbered. */ pointed-to variables are call-clobbered. */
...@@ -556,24 +562,13 @@ set_initial_properties (struct alias_info *ai) ...@@ -556,24 +562,13 @@ set_initial_properties (struct alias_info *ai)
if (tag) if (tag)
mark_call_clobbered (tag, pi->escape_mask); mark_call_clobbered (tag, pi->escape_mask);
if (pi->pt_vars) /* Defer to points-to analysis if possible, otherwise
{ clobber all addressable variables. Parameters cannot
bitmap_iterator bi; point to local memory though.
unsigned int j; ??? Properly tracking which pointers point to non-local
EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi) memory only would make a big difference here. */
{ if (!clobber_what_p_points_to (ptr)
tree alias = referenced_var (j); && !(pi->escape_mask & ESCAPE_IS_PARM))
/* 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)
{ {
any_pt_anything = true; any_pt_anything = true;
pt_anything_mask |= pi->escape_mask; pt_anything_mask |= pi->escape_mask;
......
...@@ -4664,17 +4664,19 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed, ...@@ -4664,17 +4664,19 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
|| TREE_CODE (vi->decl) == RESULT_DECL) || TREE_CODE (vi->decl) == RESULT_DECL)
{ {
/* Just add VI->DECL to the alias set. /* Just add VI->DECL to the alias set.
Don't type prune artificial vars. */ Don't type prune artificial vars or points-to sets
if (vi->is_artificial_var) 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)); bitmap_set_bit (into, DECL_UID (vi->decl));
else else
{ {
alias_set_type var_alias_set, ptr_alias_set; alias_set_type var_alias_set, ptr_alias_set;
var_alias_set = get_alias_set (vi->decl); var_alias_set = get_alias_set (vi->decl);
ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr))); ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
if (no_tbaa_pruning if (alias_sets_conflict_p (ptr_alias_set, var_alias_set))
|| (!is_derefed && !vi->directly_dereferenced)
|| alias_sets_conflict_p (ptr_alias_set, var_alias_set))
bitmap_set_bit (into, DECL_UID (vi->decl)); bitmap_set_bit (into, DECL_UID (vi->decl));
} }
} }
...@@ -4885,7 +4887,71 @@ find_what_p_points_to (tree p) ...@@ -4885,7 +4887,71 @@ find_what_p_points_to (tree p)
return false; 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. */ /* Dump points-to information to OUTFILE. */
......
...@@ -571,7 +571,9 @@ verify_flow_sensitive_alias_info (void) ...@@ -571,7 +571,9 @@ verify_flow_sensitive_alias_info (void)
goto err; 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); tree t = memory_partition (pi->name_mem_tag);
if (t == NULL_TREE) if (t == NULL_TREE)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment