re PR tree-optimization/19633 (local address incorrectly thought to escape)
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. testsuite/ChangeLog PR tree-optimization/19633 * gcc.dg/pr19633.c: New test. * gcc.dg/tree-ssa/pr19633.c: New test. From-SVN: r94311
This commit is contained in:
parent
9ff93eb01c
commit
87637d21c0
@ -1,3 +1,13 @@
|
||||
2005-01-26 Diego Novillo <dnovillo@redhat.com>
|
||||
|
||||
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 <uweigand@de.ibm.com>
|
||||
|
||||
* dbxout.c (dbxout_symbol_location): Resolve constant pool references
|
||||
|
@ -1,3 +1,9 @@
|
||||
2005-01-26 Diego Novillo <dnovillo@redhat.com>
|
||||
|
||||
PR tree-optimization/19633
|
||||
* gcc.dg/pr19633.c: New test.
|
||||
* gcc.dg/tree-ssa/pr19633.c: New test.
|
||||
|
||||
2005-01-26 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* gcc.dg/20041216-1.c: New test.
|
||||
|
40
gcc/testsuite/gcc.dg/pr19633.c
Normal file
40
gcc/testsuite/gcc.dg/pr19633.c
Normal file
@ -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;
|
||||
}
|
25
gcc/testsuite/gcc.dg/tree-ssa/pr19633.c
Normal file
25
gcc/testsuite/gcc.dg/tree-ssa/pr19633.c
Normal file
@ -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"} } */
|
@ -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);
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user