diff options
Diffstat (limited to 'gcc/tree-ssa-alias.c')
-rw-r--r-- | gcc/tree-ssa-alias.c | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 7ce016b9096..1523aebac17 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -521,6 +521,8 @@ set_initial_properties (struct alias_info *ai) referenced_var_iterator rvi; tree var; tree ptr; + bool any_pt_anything = false; + enum escape_type pt_anything_mask = 0; FOR_EACH_REFERENCED_VAR (var, rvi) { @@ -543,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. */ @@ -554,22 +562,16 @@ set_initial_properties (struct alias_info *ai) if (tag) 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 + 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)) { - 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); - } + any_pt_anything = true; + pt_anything_mask |= pi->escape_mask; } } @@ -603,6 +605,21 @@ set_initial_properties (struct alias_info *ai) MTAG_GLOBAL (tag) = true; } } + + /* If a pt_anything pointer escaped we need to mark all addressable + variables call clobbered. */ + if (any_pt_anything) + { + bitmap_iterator bi; + unsigned int j; + + EXECUTE_IF_SET_IN_BITMAP (gimple_addressable_vars (cfun), 0, j, bi) + { + tree var = referenced_var (j); + if (!unmodifiable_var_p (var)) + mark_call_clobbered (var, pt_anything_mask); + } + } } /* Compute which variables need to be marked call clobbered because |