aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@redhat.com>2005-02-23 05:08:32 +0000
committerDiego Novillo <dnovillo@gcc.gnu.org>2005-02-23 00:08:32 -0500
commit90c1d75a9bb8e25aa963da02f9c91f5f40143be1 (patch)
tree5ae2c9a5dd60102e5ee665ad3f8aaaba2450f32e /gcc
parent397763d2af80316f05484a8668c3d0dddf2c9811 (diff)
downloadgcc-90c1d75a9bb8e25aa963da02f9c91f5f40143be1.zip
gcc-90c1d75a9bb8e25aa963da02f9c91f5f40143be1.tar.gz
gcc-90c1d75a9bb8e25aa963da02f9c91f5f40143be1.tar.bz2
re PR tree-optimization/20100 (LIM is pulling out a pure function even though there is something which can modify global memory)
PR tree-optimization/20100 PR tree-optimization/20115 * tree-optimize.c (init_tree_optimization_passes): Remove pass_maybe_create_global_var. * tree-pass.h (pass_maybe_create_global_var): Remove. * tree-ssa-alias.c (aliases_computed_p): Declare. (struct alias_info): Add field NUM_PURE_CONST_CALLS_FOUND. (count_calls_and_maybe_create_global_var): Remove. (pass_maybe_create_global_var): Remove. (init_alias_info): Do not declare aliases_computed_p. (maybe_create_global_var): If the function contains no call-clobbered variables and a mix of pure/const and regular function calls, create .GLOBAL_VAR. Mark all call-clobbered variables for renaming. (merge_pointed_to_info): Update comment. (add_pointed_to_var): Likewise. (is_escape_site): Likewise. Accept struct alias_info * instead of size_t *. Update all users. Update AI->NUM_CALLS_FOUND and AI->NUM_PURE_CONST_CALLS_FOUND as necessary. * tree-ssa-operands.c (get_call_expr_operands): If ALIASES_COMPUTED_P is false, do not add call-clobbering operands. * tree-ssa.c (init_tree_ssa): Set ALIASES_COMPUTED_P to false. (delete_tree_ssa): Likewise. testsuite/ChangeLog PR tree-optimization/20100 PR tree-optimization/20115 * gcc.dg/pr20115.c: New test. * gcc.dg/pr20115-1.c: New test. * gcc.dg/pr20100.c: New test. * gcc.dg/tree-ssa/20040517-1.c: Expect virtual operands for call-clobbered variables after alias1. From-SVN: r95437
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog29
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.dg/pr20100.c32
-rw-r--r--gcc/testsuite/gcc.dg/pr20115-1.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr20115.c28
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c5
-rw-r--r--gcc/tree-optimize.c1
-rw-r--r--gcc/tree-pass.h1
-rw-r--r--gcc/tree-ssa-alias.c147
-rw-r--r--gcc/tree-ssa-operands.c12
-rw-r--r--gcc/tree-ssa.c2
11 files changed, 193 insertions, 88 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 903d625..ee37f3e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,32 @@
+2005-02-22 Diego Novillo <dnovillo@redhat.com>
+
+ PR tree-optimization/20100
+ PR tree-optimization/20115
+ * tree-optimize.c (init_tree_optimization_passes): Remove
+ pass_maybe_create_global_var.
+ * tree-pass.h (pass_maybe_create_global_var): Remove.
+ * tree-ssa-alias.c (aliases_computed_p): Declare.
+ (struct alias_info): Add field NUM_PURE_CONST_CALLS_FOUND.
+ (count_calls_and_maybe_create_global_var): Remove.
+ (pass_maybe_create_global_var): Remove.
+ (init_alias_info): Do not declare aliases_computed_p.
+ (maybe_create_global_var): If the function contains no
+ call-clobbered variables and a mix of pure/const and regular
+ function calls, create .GLOBAL_VAR.
+ Mark all call-clobbered variables for renaming.
+ (merge_pointed_to_info): Update comment.
+ (add_pointed_to_var): Likewise.
+ (is_escape_site): Likewise.
+ Accept struct alias_info * instead of size_t *.
+ Update all users.
+ Update AI->NUM_CALLS_FOUND and AI->NUM_PURE_CONST_CALLS_FOUND
+ as necessary.
+ * tree-ssa-operands.c (get_call_expr_operands): If
+ ALIASES_COMPUTED_P is false, do not add call-clobbering
+ operands.
+ * tree-ssa.c (init_tree_ssa): Set ALIASES_COMPUTED_P to false.
+ (delete_tree_ssa): Likewise.
+
2005-02-22 James E Wilson <wilson@specifixinc.com>
* toplev.c (backend_init): Don't call init_adjust_machine_modes here.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ddaa9cc..530d9a3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2005-02-22 Diego Novillo <dnovillo@redhat.com>
+
+ PR tree-optimization/20100
+ PR tree-optimization/20115
+ * gcc.dg/pr20115.c: New test.
+ * gcc.dg/pr20115-1.c: New test.
+ * gcc.dg/pr20100.c: New test.
+ * gcc.dg/tree-ssa/20040517-1.c: Expect virtual operands for
+ call-clobbered variables after alias1.
+
2005-02-22 Bud Davis <bdavis@gfortran.org>
* gfortran.dg/list_read_4.f90: new test.
diff --git a/gcc/testsuite/gcc.dg/pr20100.c b/gcc/testsuite/gcc.dg/pr20100.c
new file mode 100644
index 0000000..988fbda
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr20100.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int func_pure (void) __attribute__ ((pure));
+void func_other (int);
+int global_int;
+void abort ();
+void func_other(int a)
+{
+ if (a != global_int)
+ abort ();
+ global_int++;
+}
+
+int func_pure(void)
+{
+ return global_int;
+}
+
+int
+func_loop (int arg)
+{
+ // global_int ++;
+ while (arg--)
+ func_other (func_pure ());
+}
+
+int main(void)
+{
+ func_loop(10);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr20115-1.c b/gcc/testsuite/gcc.dg/pr20115-1.c
new file mode 100644
index 0000000..d1c4066
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr20115-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dom1" } */
+
+extern int foo (void) __attribute__((pure));
+
+int bar()
+{
+ int a = foo ();
+ a += foo ();
+ return a;
+}
+
+/* Check that we only have one call to foo. */
+/* { dg-final { scan-tree-dump-times "foo" 1 "dom1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr20115.c b/gcc/testsuite/gcc.dg/pr20115.c
new file mode 100644
index 0000000..cea4b48
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr20115.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int func_pure (void);
+void func_other (int);
+int global_int;
+int func_pure (void) { return global_int; }
+void func_other (int a)
+{
+ global_int = a + 1;
+}
+int f(void)
+{
+ int a;
+ a = func_pure();
+ func_other (a);
+ a = func_pure (); // We were removing this function call
+ return a;
+}
+void abort (void);
+
+int main(void)
+{
+ global_int = 10;
+ if (f() != 11)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c
index 5f99be2..4b09b53 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-ssa-vops" } */
+/* { dg-options "-O1 -fdump-tree-alias1-vops" } */
extern void abort (void);
int a;
@@ -17,5 +17,4 @@ void bar (void)
malloc functions may clobber global memory. Only the function result
does not alias any other pointer.
Hence, we must have a VDEF for a before and after the call to foo(). */
-/* { dg-final { scan-tree-dump-times "V_MAY_DEF" 1 "ssa"} } */
-
+/* { dg-final { scan-tree-dump-times "V_MAY_DEF" 1 "alias1"} } */
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index d2c8ede..f4ad966 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -347,7 +347,6 @@ init_tree_optimization_passes (void)
p = &pass_all_optimizations.sub;
NEXT_PASS (pass_referenced_vars);
- NEXT_PASS (pass_maybe_create_global_var);
NEXT_PASS (pass_build_ssa);
NEXT_PASS (pass_may_alias);
NEXT_PASS (pass_rename_ssa_copies);
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 6bedfcb..bf81809 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -166,6 +166,5 @@ extern struct tree_opt_pass pass_expand;
extern struct tree_opt_pass pass_rest_of_compilation;
extern struct tree_opt_pass pass_fre;
extern struct tree_opt_pass pass_linear_transform;
-extern struct tree_opt_pass pass_maybe_create_global_var;
#endif /* GCC_TREE_PASS_H */
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index bfa1685..f6cdf99 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -43,6 +43,8 @@ Boston, MA 02111-1307, USA. */
#include "convert.h"
#include "params.h"
+/* 'true' after aliases have been computed (see compute_may_aliases). */
+bool aliases_computed_p;
/* Structure to map a variable to its alias set and keep track of the
virtual operands that will be needed to represent it. */
@@ -94,6 +96,9 @@ struct alias_info
/* Number of function calls found in the program. */
size_t num_calls_found;
+ /* Number of const/pure function calls found in the program. */
+ size_t num_pure_const_calls_found;
+
/* Array of counters to keep track of how many times each pointer has
been dereferenced in the program. This is used by the alias grouping
heuristic in compute_flow_insensitive_aliasing. */
@@ -145,7 +150,7 @@ static void compute_points_to_and_addr_escape (struct alias_info *);
static void compute_flow_sensitive_aliasing (struct alias_info *);
static void setup_pointers_and_addressables (struct alias_info *);
static bool collect_points_to_info_r (tree, tree, void *);
-static bool is_escape_site (tree, size_t *);
+static bool is_escape_site (tree, struct alias_info *);
static void add_pointed_to_var (struct alias_info *, tree, tree);
static void create_global_var (void);
static void collect_points_to_info_for (struct alias_info *, tree);
@@ -465,70 +470,12 @@ count_uses_and_derefs (tree ptr, tree stmt, unsigned *num_uses_p,
}
-/* Count the number of calls in the function and conditionally
- create GLOBAL_VAR. This is performed before translation
- into SSA (and thus before alias analysis) to avoid compile time
- and memory utilization explosions in functions with many
- of calls and call clobbered variables. */
-
-static void
-count_calls_and_maybe_create_global_var (void)
-{
- struct alias_info ai;
- basic_block bb;
- bool temp;
-
- memset (&ai, 0, sizeof (struct alias_info));
-
- /* First count the number of calls in the IL. */
- FOR_EACH_BB (bb)
- {
- block_stmt_iterator si;
-
- for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
- {
- tree stmt = bsi_stmt (si);
-
- if (get_call_expr_in (stmt) != NULL_TREE)
- ai.num_calls_found++;
- }
- }
-
- /* If there are no call clobbered variables, then maybe_create_global_var
- will always create a GLOBAL_VAR. At this point we do not want that
- behavior. So we turn on one bit in CALL_CLOBBERED_VARs, call
- maybe_create_global_var, then reset the bit to its original state. */
- temp = bitmap_bit_p (call_clobbered_vars, 0);
- bitmap_set_bit (call_clobbered_vars, 0);
- maybe_create_global_var (&ai);
- if (!temp)
- bitmap_clear_bit (call_clobbered_vars, 0);
-}
-
-struct tree_opt_pass pass_maybe_create_global_var =
-{
- "maybe_create_global_var", /* name */
- NULL, /* gate */
- count_calls_and_maybe_create_global_var, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_TREE_MAY_ALIAS, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
- 0 /* letter */
-};
-
/* Initialize the data structures used for alias analysis. */
static struct alias_info *
init_alias_info (void)
{
struct alias_info *ai;
- static bool aliases_computed_p = false;
ai = xcalloc (1, sizeof (struct alias_info));
ai->ssa_names_visited = sbitmap_alloc (num_ssa_names);
@@ -695,7 +642,7 @@ compute_points_to_and_addr_escape (struct alias_info *ai)
{
bitmap addr_taken;
tree stmt = bsi_stmt (si);
- bool stmt_escapes_p = is_escape_site (stmt, &ai->num_calls_found);
+ bool stmt_escapes_p = is_escape_site (stmt, ai);
bitmap_iterator bi;
/* Mark all the variables whose address are taken by the
@@ -1586,22 +1533,56 @@ maybe_create_global_var (struct alias_info *ai)
n_clobbered++;
}
- if (ai->num_calls_found * n_clobbered >= (size_t) GLOBAL_VAR_THRESHOLD)
+ /* If the number of virtual operands that would be needed to
+ model all the call-clobbered variables is larger than
+ GLOBAL_VAR_THRESHOLD, create .GLOBAL_VAR.
+
+ Also create .GLOBAL_VAR if there are no call-clobbered
+ variables and the program contains a mixture of pure/const
+ and regular function calls. This is to avoid the problem
+ described in PR 20115:
+
+ int X;
+ int func_pure (void) { return X; }
+ int func_non_pure (int a) { X += a; }
+ int foo ()
+ {
+ int a = func_pure ();
+ func_non_pure (a);
+ a = func_pure ();
+ return a;
+ }
+
+ Since foo() has no call-clobbered variables, there is
+ no relationship between the calls to func_pure and
+ func_non_pure. Since func_pure has no side-effects, value
+ numbering optimizations elide the second call to func_pure.
+ So, if we have some pure/const and some regular calls in the
+ program we create .GLOBAL_VAR to avoid missing these
+ relations. */
+ if (ai->num_calls_found * n_clobbered >= (size_t) GLOBAL_VAR_THRESHOLD
+ || (n_clobbered == 0
+ && ai->num_calls_found > 0
+ && ai->num_pure_const_calls_found > 0
+ && ai->num_calls_found > ai->num_pure_const_calls_found))
create_global_var ();
}
- /* If the function has calls to clobbering functions and .GLOBAL_VAR has
- been created, make it an alias for all call-clobbered variables. */
- if (global_var)
- EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
- {
- tree var = referenced_var (i);
- if (var != global_var)
- {
- add_may_alias (var, global_var);
- bitmap_set_bit (vars_to_rename, var_ann (var)->uid);
- }
- }
+ /* Mark all call-clobbered symbols for renaming. Since the initial
+ rewrite into SSA ignored all call sites, we may need to rename
+ .GLOBAL_VAR and the call-clobbered variables. */
+ EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
+ {
+ tree var = referenced_var (i);
+
+ /* If the function has calls to clobbering functions and
+ .GLOBAL_VAR has been created, make it an alias for all
+ call-clobbered variables. */
+ if (global_var && var != global_var)
+ add_may_alias (var, global_var);
+
+ bitmap_set_bit (vars_to_rename, var_ann (var)->uid);
+ }
}
@@ -1762,8 +1743,8 @@ set_pt_malloc (tree ptr)
/* Given two different pointers DEST and ORIG. Merge the points-to
- information in ORIG into DEST. AI is as in
- collect_points_to_info. */
+ information in ORIG into DEST. AI contains all the alias
+ information collected up to this point. */
static void
merge_pointed_to_info (struct alias_info *ai, tree dest, tree orig)
@@ -1908,7 +1889,7 @@ add_pointed_to_expr (struct alias_info *ai, tree ptr, tree expr)
/* If VALUE is of the form &DECL, add DECL to the set of variables
pointed-to by PTR. Otherwise, add VALUE as a pointed-to expression by
- PTR. AI is as in collect_points_to_info. */
+ PTR. AI points to the collected alias information. */
static void
add_pointed_to_var (struct alias_info *ai, tree ptr, tree value)
@@ -2040,16 +2021,18 @@ collect_points_to_info_r (tree var, tree stmt, void *data)
3- STMT is an assignment to a non-local variable, or
4- STMT is a return statement.
- If NUM_CALLS_P is not NULL, the counter is incremented if STMT contains
- a function call. */
+ AI points to the alias information collected so far. */
static bool
-is_escape_site (tree stmt, size_t *num_calls_p)
+is_escape_site (tree stmt, struct alias_info *ai)
{
- if (get_call_expr_in (stmt) != NULL_TREE)
+ tree call = get_call_expr_in (stmt);
+ if (call != NULL_TREE)
{
- if (num_calls_p)
- (*num_calls_p)++;
+ ai->num_calls_found++;
+
+ if (!TREE_SIDE_EFFECTS (call))
+ ai->num_pure_const_calls_found++;
return true;
}
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 0f27912..3b5de9b 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -1460,7 +1460,17 @@ get_call_expr_operands (tree stmt, tree expr)
tree op;
int call_flags = call_expr_flags (expr);
- if (!bitmap_empty_p (call_clobbered_vars))
+ /* If aliases have been computed already, add V_MAY_DEF or V_USE
+ operands for all the symbols that have been found to be
+ call-clobbered.
+
+ Note that if aliases have not been computed, the global effects
+ of calls will not be included in the SSA web. This is fine
+ because no optimizer should run before aliases have been
+ computed. By not bothering with virtual operands for CALL_EXPRs
+ we avoid adding superfluous virtual operands, which can be a
+ significant compile time sink (See PR 15855). */
+ if (aliases_computed_p && !bitmap_empty_p (call_clobbered_vars))
{
/* A 'pure' or a 'const' functions never call clobber anything.
A 'noreturn' function might, but since we don't return anyway
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 56a181a..b39c260 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -723,6 +723,7 @@ init_tree_ssa (void)
init_ssanames ();
init_phinodes ();
global_var = NULL_TREE;
+ aliases_computed_p = false;
}
@@ -767,6 +768,7 @@ delete_tree_ssa (void)
BITMAP_FREE (addressable_vars);
addressable_vars = NULL;
modified_noreturn_calls = NULL;
+ aliases_computed_p = false;
}