This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[improved-aliasing]: Fix PR tree-optimization/24287
- From: Daniel Berlin <dberlin at dberlin dot org>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 18 Oct 2005 17:50:57 -0400
- Subject: [improved-aliasing]: Fix PR tree-optimization/24287
This patch causes us to know that things that escape only to pure/const
functions aren't clobbered by the non-pure/const ones, and only read by
the pure/const ones.
Any good context-sensitive mod-ref algorithm would discover this on it's
own, but since we don't have one yet, might as well do the best we can
with what we have.
It also fixes the imprecision that we used to consider anything that had
pt_anything set to have it's value escape, which is not really true.
Things escape only because they escape, not because they point to
anything.
Fixing this required teaching it that incoming pointers value-escape by
default.
Bootstrapped and regtested on i686-pc-linux-gnu
Committed to improved-aliasing
--Dan
2005-10-18 Daniel Berlin <dberlin@dberlin.org>
Fix PR tree-optimization/24287
* tree-dfa.c (dump_variable): Print reasons for call clobbering.
* tree-flow.h (struct ptr_info_def): Add escape mask to pointer.
(ESCAPE_TRANSITIVE): Removed.
(ESCAPE_TO_PURE_CONST): New.
(ESCAPE_IS_PARM): New.
(ESCAPE_UNKNOWN): New.
* tree-ssa-alias.c (set_initial_properties): Incoming pointers are
value escaping.
Pointers that point to anything are not.
Use pointer escape mask.
(is_escape_site): Use ESCAPE_TO_PURE_CONST.
* tree-ssa-operands.c (add_call_clobber_ops): Clean up a bit.
Things that *only* escape to pure/const functions are only read by
pure/const functions, and are not clobbered by the non-pure/const
functions.
(add_call_read_ops): Cleanup.
* tree-ssa-structalias.c (update_alias_info): Use pi->escape_mask,
not v_ann.
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dfa.c,v
retrieving revision 2.63.4.6
diff -u -p -r2.63.4.6 tree-dfa.c
--- tree-dfa.c 18 Oct 2005 15:35:40 -0000 2.63.4.6
+++ tree-dfa.c 18 Oct 2005 21:42:17 -0000
@@ -353,7 +353,35 @@ dump_variable (FILE *file, tree var)
fprintf (file, ", is volatile");
if (is_call_clobbered (var))
- fprintf (file, ", call clobbered");
+ {
+ fprintf (file, ", call clobbered");
+ if (dump_flags & TDF_DETAILS)
+ {
+ var_ann_t va = var_ann (var);
+ unsigned int escape_mask = va->escape_mask;
+
+ fprintf (file, " (");
+ if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
+ fprintf (file, ", stored in global");
+ if (escape_mask & ESCAPE_TO_ASM)
+ fprintf (file, ", goes through ASM");
+ if (escape_mask & ESCAPE_TO_CALL)
+ fprintf (file, ", passed to call");
+ if (escape_mask & ESCAPE_BAD_CAST)
+ fprintf (file, ", bad cast");
+ if (escape_mask & ESCAPE_TO_RETURN)
+ fprintf (file, ", returned from func");
+ if (escape_mask & ESCAPE_TO_PURE_CONST)
+ fprintf (file, ", passed to pure/const");
+ if (escape_mask & ESCAPE_IS_GLOBAL)
+ fprintf (file, ", is global var");
+ if (escape_mask & ESCAPE_IS_PARM)
+ fprintf (file, ", is incoming pointer");
+ if (escape_mask & ESCAPE_UNKNOWN)
+ fprintf (file, ", unknown escape");
+ fprintf (file, " )");
+ }
+ }
if (default_def (var))
{
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.132.2.8
diff -u -p -r2.132.2.8 tree-flow.h
--- tree-flow.h 18 Oct 2005 15:35:40 -0000 2.132.2.8
+++ tree-flow.h 18 Oct 2005 21:42:17 -0000
@@ -92,6 +92,9 @@ struct ptr_info_def GTY(())
pointer will be represented by this memory tag, instead of the type
tag computed by TBAA. */
tree name_mem_tag;
+
+ /* Mask of reasons this pointer's value escapes the function */
+ unsigned int escape_mask;
};
@@ -777,9 +780,10 @@ enum escape_type
ESCAPE_TO_CALL = 1 << 3,
ESCAPE_BAD_CAST = 1 << 4,
ESCAPE_TO_RETURN = 1 << 5,
- ESCAPE_TRANSITIVE = 1 << 6,
+ ESCAPE_TO_PURE_CONST = 1 << 6,
ESCAPE_IS_GLOBAL = 1 << 7,
- ESCAPE_UNKNOWN = 1 << 8
+ ESCAPE_IS_PARM = 1 << 8,
+ ESCAPE_UNKNOWN = 1 << 9
};
/* In tree-flow-inline.h */
Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-alias.c,v
retrieving revision 2.109.4.11
diff -u -p -r2.109.4.11 tree-ssa-alias.c
--- tree-ssa-alias.c 18 Oct 2005 15:35:40 -0000 2.109.4.11
+++ tree-ssa-alias.c 18 Oct 2005 21:42:18 -0000
@@ -327,8 +327,18 @@ set_initial_properties (struct alias_inf
if (is_global_var (var)
&& (!var_can_have_subvars (var)
|| get_subvars_for_var (var) == NULL))
- if (!unmodifiable_var_p (var))
- mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
+ {
+ if (!unmodifiable_var_p (var))
+ mark_call_clobbered (var, ESCAPE_IS_GLOBAL);
+ }
+ else if (TREE_CODE (var) == PARM_DECL
+ && default_def (var)
+ && POINTER_TYPE_P (TREE_TYPE (var)))
+ {
+ tree def = default_def (var);
+ get_ptr_info (def)->value_escapes_p = 1;
+ get_ptr_info (def)->escape_mask |= ESCAPE_IS_PARM;
+ }
}
for (i = 0; i < VARRAY_ACTIVE_SIZE (ai->processed_ptrs); i++)
@@ -336,16 +346,16 @@ set_initial_properties (struct alias_inf
tree ptr = VARRAY_TREE (ai->processed_ptrs, i);
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
var_ann_t v_ann = var_ann (SSA_NAME_VAR (ptr));
-
- if (pi->value_escapes_p || pi->pt_anything)
+
+ if (pi->value_escapes_p)
{
- /* If PTR escapes or may point to anything, then its associated
- memory tags and pointed-to variables are call-clobbered. */
+ /* If PTR escapes then its associated memory tags and
+ pointed-to variables are call-clobbered. */
if (pi->name_mem_tag)
- mark_call_clobbered (pi->name_mem_tag, v_ann->escape_mask);
+ mark_call_clobbered (pi->name_mem_tag, pi->escape_mask);
if (v_ann->type_mem_tag)
- mark_call_clobbered (v_ann->type_mem_tag, v_ann->escape_mask);
+ mark_call_clobbered (v_ann->type_mem_tag, pi->escape_mask);
if (pi->pt_vars)
{
@@ -353,7 +363,7 @@ set_initial_properties (struct alias_inf
unsigned int j;
EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, j, bi)
if (!unmodifiable_var_p (referenced_var (j)))
- mark_call_clobbered (referenced_var (j), v_ann->escape_mask);
+ mark_call_clobbered (referenced_var (j), pi->escape_mask);
}
}
/* If the name tag is call clobbered, so is the type tag
@@ -361,7 +371,7 @@ set_initial_properties (struct alias_inf
if (pi->name_mem_tag
&& v_ann->type_mem_tag
&& is_call_clobbered (pi->name_mem_tag))
- mark_call_clobbered (v_ann->type_mem_tag, v_ann->escape_mask);
+ mark_call_clobbered (v_ann->type_mem_tag, pi->escape_mask);
if ((pi->pt_global_mem || pi->pt_anything) && pi->name_mem_tag)
mark_tag_global (pi->name_mem_tag);
@@ -1890,7 +1900,10 @@ is_escape_site (tree stmt, struct alias_
ai->num_calls_found++;
if (!TREE_SIDE_EFFECTS (call))
- ai->num_pure_const_calls_found++;
+ {
+ ai->num_pure_const_calls_found++;
+ return ESCAPE_TO_PURE_CONST;
+ }
return ESCAPE_TO_CALL;
}
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.100.4.7
diff -u -p -r2.100.4.7 tree-ssa-operands.c
--- tree-ssa-operands.c 18 Oct 2005 15:35:41 -0000 2.100.4.7
+++ tree-ssa-operands.c 18 Oct 2005 21:42:18 -0000
@@ -1860,7 +1860,6 @@ add_call_clobber_ops (tree stmt, tree ca
struct cgraph_node *ournode = cgraph_node (current_function_decl);
bool okay_for_call_skip = callee_okay_for_noescape (ournode, callee);
-
/* Functions that are not const, pure or never return may clobber
call-clobbered variables. */
if (s_ann)
@@ -1888,28 +1887,45 @@ add_call_clobber_ops (tree stmt, tree ca
/* Add a V_MAY_DEF operand for every call clobbered variable. */
EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
{
- tree var = referenced_var (u);
+ tree var = referenced_var_lookup (u);
+ unsigned int escape_mask = var_ann (var)->escape_mask;
bool not_read
= not_read_b ? bitmap_bit_p (not_read_b, u) : false;
bool not_written
= not_written_b ? bitmap_bit_p (not_written_b, u) : false;
- bool before = okay_for_call_skip;
gcc_assert (!unmodifiable_var_p (var));
clobber_stats.clobbered_vars++;
+
/* See if this variable is really clobbered by this function. */
- if (okay_for_call_skip)
+
+ /* Trivial case: Things escaping only to pure/const are not
+ clobbered by non-pure-const, and only read by pure/const. */
+ if ((escape_mask & ~(ESCAPE_TO_PURE_CONST)) == 0)
{
- okay_for_call_skip &= (var_ann (var)->escape_mask & ~(ESCAPE_TO_CALL)) == 0;
- if (okay_for_call_skip)
+ tree call = get_call_expr_in (stmt);
+ if (call_expr_flags (call) & (ECF_CONST | ECF_PURE))
+ {
+ add_stmt_operand (&var, s_ann, opf_none);
+ clobber_stats.unescapable_clobbers_avoided++;
+ continue;
+ }
+ else
{
clobber_stats.unescapable_clobbers_avoided++;
continue;
}
}
- okay_for_call_skip = before;
+
+ /* Otherwise, see if we know it doesn't escape to *this*
+ function. */
+ if (okay_for_call_skip && (escape_mask & ~(ESCAPE_TO_CALL | ESCAPE_TO_PURE_CONST)) == 0)
+ {
+ clobber_stats.unescapable_clobbers_avoided++;
+ continue;
+ }
if (not_written)
{
@@ -1954,9 +1970,9 @@ add_call_read_ops (tree stmt, tree calle
EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
{
tree var = referenced_var (u);
+ var_ann_t va = var_ann (var);
bool not_read = not_read_b ? bitmap_bit_p (not_read_b, u) : false;
- bool before = okay_for_call_skip;
-
+
clobber_stats.readonly_clobbers++;
if (not_read)
@@ -1965,18 +1981,13 @@ add_call_read_ops (tree stmt, tree calle
continue;
}
- if (okay_for_call_skip)
+ if (okay_for_call_skip && (va->escape_mask & ~(ESCAPE_TO_CALL | ESCAPE_TO_PURE_CONST)) == 0)
{
- okay_for_call_skip &= (var_ann (var)->escape_mask & ~(ESCAPE_TO_CALL)) == 0;
- if (okay_for_call_skip)
- {
- clobber_stats.unescapable_clobbers_avoided++;
- continue;
- }
+ clobber_stats.unescapable_clobbers_avoided++;
+ continue;
}
add_stmt_operand (&var, s_ann, opf_none | opf_non_specific);
- okay_for_call_skip = before;
}
}
Index: tree-ssa-structalias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-structalias.c,v
retrieving revision 2.27.2.10
diff -u -p -r2.27.2.10 tree-ssa-structalias.c
--- tree-ssa-structalias.c 18 Oct 2005 15:35:41 -0000 2.27.2.10
+++ tree-ssa-structalias.c 18 Oct 2005 21:42:19 -0000
@@ -2998,7 +2998,7 @@ update_alias_info (tree stmt, struct ali
escapes and so the pointed-to variables need to
be marked call-clobbered. */
pi->value_escapes_p = 1;
- v_ann->escape_mask |= stmt_escape_type;
+ pi->escape_mask |= stmt_escape_type;
/* If the statement makes a function call, assume
that pointer OP will be dereferenced in a store
Index: testsuite/gcc.dg/tree-ssa/pr24287.c
===================================================================
RCS file: testsuite/gcc.dg/tree-ssa/pr24287.c
diff -N testsuite/gcc.dg/tree-ssa/pr24287.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/tree-ssa/pr24287.c 18 Oct 2005 21:42:22 -0000
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+int g1(int);
+int h(int *a, int *b)__attribute__((pure));
+void link_error();
+
+/* The calls to link_error should be eliminated, since nothing escapes to
+ non-pure functions. */
+int g(void)
+{
+ int t = 0, t1 = 2;
+ int t2 = h(&t, &t1);
+ if (t != 0)
+ link_error ();
+ if (t1 != 2)
+ link_error ();
+ g1(t2);
+ if (t != 0)
+ link_error ();
+ if (t1 != 2)
+ link_error ();
+ return t2 == 2;
+}
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */