diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ca995ccadfe..04ef3579952 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2005-01-26 Diego Novillo + + PR tree-optimization/19633 + * tree-ssa-alias.c (ptr_is_dereferenced_by): Also handle + CALL_EXPRs. + (maybe_create_global_var): Do not create .GLOBAL_VAR if there + are no call-clobbered variables. + * tree-outof-ssa.c (check_replaceable): Return false for calls + with side-effects. + 2005-01-26 Ulrich Weigand * dbxout.c (dbxout_symbol_location): Resolve constant pool references diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0140e9aa7e4..deceb4abe19 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-01-26 Diego Novillo + + PR tree-optimization/19633 + * gcc.dg/pr19633.c: New test. + * gcc.dg/tree-ssa/pr19633.c: New test. + 2005-01-26 Ulrich Weigand * gcc.dg/20041216-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr19633.c b/gcc/testsuite/gcc.dg/pr19633.c new file mode 100644 index 00000000000..4e18375656f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr19633.c @@ -0,0 +1,40 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +struct S +{ + int w, x, y, z; +}; + +struct T +{ + int r; + struct S s; +}; + +void +foo (int a, struct T b) +{ + struct S x; + struct S *c = &x; + if (a) + c = &b.s; + b.s.w = 3; + bar (*c, a); + if (b.s.w != 3) + link_error (); +} + +int main () +{ + struct T b; + foo (3, b); + return 0; +} + +int X; + +int bar (struct S x, int i) +{ + X = 3; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19633.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19633.c new file mode 100644 index 00000000000..88cbfe222d7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19633.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-ssa-vops" } */ +struct S +{ + int w, x, y, z; +}; +struct T +{ + int r; + struct S s; +}; +void bar (struct S, int); +void +foo (int a, struct T b) +{ + struct S x; + struct S *c = &x; + if (a) + c = &b.s; + bar (*c, a); +} + +/* Make sure that .GLOBAL_VAR is not created when there are no + clobbering calls. */ +/* { dg-final { scan-tree-dump-times "GLOBAL_VAR" 0 "ssa"} } */ diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index cfa17043ca6..430e8cae58a 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -1460,6 +1460,7 @@ check_replaceable (temp_expr_table_p tab, tree stmt) int num_use_ops, version; var_map map = tab->map; ssa_op_iter iter; + tree call_expr; if (TREE_CODE (stmt) != MODIFY_EXPR) return false; @@ -1486,6 +1487,15 @@ check_replaceable (temp_expr_table_p tab, tree stmt) if (flag_float_store && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 1)))) return false; + /* Calls to functions with side-effects cannot be replaced. */ + if ((call_expr = get_call_expr_in (stmt)) != NULL_TREE) + { + int call_flags = call_expr_flags (call_expr); + if (TREE_SIDE_EFFECTS (call_expr) + && !(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN))) + return false; + } + uses = USE_OPS (ann); num_use_ops = NUM_USES (uses); vuseops = VUSE_OPS (ann); diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index a41021792a7..da11fd03fa1 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -621,6 +621,16 @@ ptr_is_dereferenced_by (tree ptr, tree stmt, bool *is_store) return true; } } + else + { + /* CALL_EXPRs may also contain pointer dereferences for types + that are not GIMPLE register types. If the CALL_EXPR is on + the RHS of an assignment, it will be handled by the + MODIFY_EXPR handler above. */ + tree call = get_call_expr_in (stmt); + if (call && walk_tree (&call, find_ptr_dereference, ptr, NULL)) + return true; + } return false; } @@ -1538,26 +1548,7 @@ maybe_create_global_var (struct alias_info *ai) n_clobbered++; } - /* Create .GLOBAL_VAR if we have too many call-clobbered - variables. We also create .GLOBAL_VAR when there no - 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) + if (ai->num_calls_found * n_clobbered >= (size_t) GLOBAL_VAR_THRESHOLD) create_global_var (); }