This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Fix handling of function calls with side effects
- From: Diego Novillo <dnovillo at redhat dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 26 Mar 2004 16:17:54 -0500
- Subject: [tree-ssa] Fix handling of function calls with side effects
- Organization: Red Hat Canada
When a program has no call-clobbered variables, the compiler would not
create .GLOBAL_VAR (the artificial variable used to model side
effects). This was causing the expression recombination pass to move
function calls past others:
a = foo()
bar();
baz(a); <-- foo() was being moved here.
If bar() depends on some global variable set by foo(), we have a
problem.
Jeff found this as a runtime failure in one of the FC2 packages
(temacs?). This patch fixes the problem.
It also fixes the handling of asm memory barriers to add a VDEF to
.GLOBAL_VAR even if there are no call-clobbered variables in the
function.
Bootstrapped x86, x86-64.
Diego.
* tree-ssa-alias.c (maybe_create_global_var): Create
.GLOBAL_VAR if there are no call-clobbered variables.
* tree-ssa-operands.c (get_stmt_operands): Add call-clobbering
VDEFs for asm ("":::"memory") if there are call-clobbered
variables or if .GLOBAL_VAR has been created.
testsuite/ChangeLog.tree-ssa:
* gcc.dg/tree-ssa/20040326-1.c: New test.
Index: tree-ssa-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-alias.c,v
retrieving revision 1.1.2.16
diff -d -c -p -d -u -p -r1.1.2.16 tree-ssa-alias.c
--- tree-ssa-alias.c 25 Mar 2004 18:41:36 -0000 1.1.2.16
+++ tree-ssa-alias.c 26 Mar 2004 17:58:36 -0000
@@ -1304,7 +1304,25 @@ maybe_create_global_var (struct alias_in
n_clobbered = 0;
EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, n_clobbered++);
- if (ai->num_calls_found * n_clobbered >= (size_t) GLOBAL_VAR_THRESHOLD)
+ /* Create .GLOBAL_VAR if we have too many call-clobbered variables.
+ We also create .GLOBAL_VAR when there no are call-clobbered variables
+ to prevent code motion transformations from re-arranging function
+ calls that may have side effects. For instance,
+
+ foo ()
+ {
+ int a = f ();
+ g ();
+ h (a);
+ }
+
+ There are no call-clobbered variables in foo(), so it would be
+ entirely possible for a pass to want to move the call to f()
+ after the call to g(). If f() has side effects, that would be
+ wrong. Creating .GLOBAL_VAR in this case will insert VDEFs for
+ it and prevent such transformations. */
+ if (n_clobbered == 0
+ || ai->num_calls_found * n_clobbered >= (size_t) GLOBAL_VAR_THRESHOLD)
create_global_var ();
/* If the function has calls to clobbering functions and .GLOBAL_VAR has
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-operands.c,v
retrieving revision 1.1.2.17
diff -d -c -p -d -u -p -r1.1.2.17 tree-ssa-operands.c
--- tree-ssa-operands.c 16 Mar 2004 22:31:56 -0000 1.1.2.17
+++ tree-ssa-operands.c 26 Mar 2004 17:58:36 -0000
@@ -769,10 +769,12 @@ get_stmt_operands (tree stmt)
get_expr_operands (stmt, &TREE_VALUE (link), 0, &prev_vops);
}
- for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
- if (!strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory")
- && bitmap_first_set_bit (call_clobbered_vars) >= 0)
- add_call_clobber_ops (stmt, &prev_vops);
+ /* Clobber memory for asm ("" : : : "memory"); */
+ if (global_var
+ || bitmap_first_set_bit (call_clobbered_vars) >= 0)
+ for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
+ if (!strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory"))
+ add_call_clobber_ops (stmt, &prev_vops);
}
break;
Index: testsuite/gcc.dg/tree-ssa/20040326-1.c
===================================================================
RCS file: testsuite/gcc.dg/tree-ssa/20040326-1.c
diff -N testsuite/gcc.dg/tree-ssa/20040326-1.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/tree-ssa/20040326-1.c 26 Mar 2004 21:10:51 -0000
@@ -0,0 +1,29 @@
+/* { dg-options "-O2 -fno-inline-functions" } */
+/* { dg-do run } */
+/* When there are no call-clobbered variables, we should still create
+ a .GLOBAL_VAR to model the side effects of functions. Without it,
+ we were moving the call to Faref() inside the second call to
+ Faset(). */
+main ()
+{
+ int table, c, elt;
+ int tem = Faref (table, elt);
+ Faset (table, elt, c);
+ Faset (table, c, tem);/* tem cannot be replaced with Faref (table, elt) */
+ exit (0);
+}
+
+int j = 0;
+
+int __attribute__ ((noinline)) Faref (table, elt)
+{
+ j = 1;
+ return 0;
+}
+
+int __attribute__ ((noinline)) Faset (table, elt, c)
+{
+ if (j != 1)
+ abort ();
+ return 0;
+}