mirror of git://gcc.gnu.org/git/gcc.git
re PR tree-optimization/19831 (Missing DSE/malloc/free optimization)
2009-07-01 Richard Guenther <rguenther@suse.de> PR tree-optimization/19831 * tree-ssa-dce.c (propagate_necessity): Calls to functions that only act as barriers do not make any previous stores necessary. * tree-ssa-structalias.c (handle_lhs_call): Delay making HEAP variables global, do not add a constraint from nonlocal. (find_func_aliases): Handle escapes through return statements. (compute_points_to_sets): Make escaped HEAP variables global. * gcc.dg/tree-ssa/20041122-1.c: Enable TBAA, scan FRE dump, make allocated memory escape. Un-XFAIL. * gcc.dg/vect/pr21591.c: Make allocated memory escape. * gcc.dg/vect/pr31699.c: Likewise. * gcc.dg/tree-ssa/ssa-dce-7.c: New testcase. libmudflap/ * testsuite/libmudflap.c/fail11-frag.c: Make allocated memory escape. * testsuite/libmudflap.c/fail12-frag.c: Likewise. * testsuite/libmudflap.c/fail16-frag.c: Likewise. * testsuite/libmudflap.c/fail31-frag.c: Likewise. From-SVN: r149140
This commit is contained in:
parent
f6e0880aa0
commit
14c41b9bb9
|
@ -1,3 +1,14 @@
|
||||||
|
2009-07-01 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/19831
|
||||||
|
* tree-ssa-dce.c (propagate_necessity): Calls to functions
|
||||||
|
that only act as barriers do not make any previous stores
|
||||||
|
necessary.
|
||||||
|
* tree-ssa-structalias.c (handle_lhs_call): Delay making
|
||||||
|
HEAP variables global, do not add a constraint from nonlocal.
|
||||||
|
(find_func_aliases): Handle escapes through return statements.
|
||||||
|
(compute_points_to_sets): Make escaped HEAP variables global.
|
||||||
|
|
||||||
2009-07-01 Paolo Bonzini <bonzini@gnu.org>
|
2009-07-01 Paolo Bonzini <bonzini@gnu.org>
|
||||||
|
|
||||||
PR bootstrap/40597
|
PR bootstrap/40597
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
2009-07-01 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/19831
|
||||||
|
* gcc.dg/tree-ssa/20041122-1.c: Enable TBAA, scan FRE dump,
|
||||||
|
make allocated memory escape. Un-XFAIL.
|
||||||
|
* gcc.dg/vect/pr21591.c: Make allocated memory escape.
|
||||||
|
* gcc.dg/vect/pr31699.c: Likewise.
|
||||||
|
* gcc.dg/tree-ssa/ssa-dce-7.c: New testcase.
|
||||||
|
|
||||||
2009-06-30 Jakub Jelinek <jakub@redhat.com>
|
2009-06-30 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR c++/40566
|
PR c++/40566
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* { dg-do compile } */
|
/* { dg-do compile } */
|
||||||
/* { dg-options "-O1 -fdump-tree-dom2" } */
|
/* { dg-options "-O1 -fstrict-aliasing -fdump-tree-fre" } */
|
||||||
|
|
||||||
|
|
||||||
__extension__ typedef __SIZE_TYPE__ size_t;
|
__extension__ typedef __SIZE_TYPE__ size_t;
|
||||||
extern void *xmalloc (size_t) __attribute__ ((__malloc__));
|
extern void *xmalloc (size_t) __attribute__ ((__malloc__));
|
||||||
|
@ -17,10 +16,10 @@ struct basic_block_def
|
||||||
typedef struct basic_block_def *basic_block;
|
typedef struct basic_block_def *basic_block;
|
||||||
extern int n_basic_blocks;
|
extern int n_basic_blocks;
|
||||||
extern edge frob ();
|
extern edge frob ();
|
||||||
void
|
basic_block *
|
||||||
find_unreachable_blocks (int frobit)
|
find_unreachable_blocks (void)
|
||||||
{
|
{
|
||||||
basic_block *tos, *worklist, bb;
|
basic_block *tos, *worklist;
|
||||||
tos = worklist = xmalloc (sizeof (basic_block) * n_basic_blocks);
|
tos = worklist = xmalloc (sizeof (basic_block) * n_basic_blocks);
|
||||||
edge e = frob();
|
edge e = frob();
|
||||||
if (!(e->dest->flags & 4))
|
if (!(e->dest->flags & 4))
|
||||||
|
@ -28,11 +27,12 @@ find_unreachable_blocks (int frobit)
|
||||||
e->dest->flags |= 4;
|
e->dest->flags |= 4;
|
||||||
*tos++ = e->dest;
|
*tos++ = e->dest;
|
||||||
}
|
}
|
||||||
|
return worklist;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the aliasing code does its job properly, then we should be
|
/* If the aliasing code does its job properly, then we should be
|
||||||
able to determine that modifying e->dest->flags does not
|
able to determine that modifying e->dest->flags does not
|
||||||
modify e or e->dest. The net result is that we only need one
|
modify e or e->dest if we can assert strict-aliasing rules.
|
||||||
load of e->dest. */
|
The net result is that we only need one load of e->dest. */
|
||||||
/* { dg-final { scan-tree-dump-times "->dest" 1 "dom2" { xfail *-*-* } } } */
|
/* { dg-final { scan-tree-dump-times "->dest" 1 "fre" } } */
|
||||||
/* { dg-final { cleanup-tree-dump "dom2" } } */
|
/* { dg-final { cleanup-tree-dump "fre" } } */
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/* { dg-do link } */
|
||||||
|
/* { dg-options "-O -fdump-tree-optimized" } */
|
||||||
|
|
||||||
|
extern void link_error (void);
|
||||||
|
void foo(int n)
|
||||||
|
{
|
||||||
|
int * f = (int*) __builtin_malloc (n * sizeof (int));
|
||||||
|
int * ff = (int*) __builtin_malloc (n * sizeof (int));
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
f[i] = 1;
|
||||||
|
ff[i] = 2;
|
||||||
|
if (f[i] != 1)
|
||||||
|
link_error ();
|
||||||
|
if (ff[i] != 2)
|
||||||
|
link_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
__builtin_free (f);
|
||||||
|
__builtin_free (ff);
|
||||||
|
}
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We should have removed the calls to link_error () and all stores
|
||||||
|
to the allocated memory. */
|
||||||
|
|
||||||
|
/* { dg-final { scan-tree-dump-times "\\\*D" 0 "optimized" } } */
|
||||||
|
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
|
@ -10,6 +10,8 @@ struct a
|
||||||
struct a *malloc1(__SIZE_TYPE__) __attribute__((malloc));
|
struct a *malloc1(__SIZE_TYPE__) __attribute__((malloc));
|
||||||
void free(void*);
|
void free(void*);
|
||||||
|
|
||||||
|
struct a *p, *q, *r;
|
||||||
|
|
||||||
void f(void)
|
void f(void)
|
||||||
{
|
{
|
||||||
struct a *a = malloc1(sizeof(struct a));
|
struct a *a = malloc1(sizeof(struct a));
|
||||||
|
@ -26,9 +28,9 @@ void f(void)
|
||||||
{
|
{
|
||||||
a->a1[i] = b->a1[i] + c->a1[i];
|
a->a1[i] = b->a1[i] + c->a1[i];
|
||||||
}
|
}
|
||||||
free(a);
|
p = a;
|
||||||
free(b);
|
q = b;
|
||||||
free(c);
|
r = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
|
/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
|
||||||
|
|
|
@ -7,13 +7,15 @@
|
||||||
float x[256];
|
float x[256];
|
||||||
|
|
||||||
__attribute__ ((noinline))
|
__attribute__ ((noinline))
|
||||||
void foo(void)
|
double *foo(void)
|
||||||
{
|
{
|
||||||
double *z = malloc (sizeof(double) * 256);
|
double *z = malloc (sizeof(double) * 256);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<256; ++i)
|
for (i=0; i<256; ++i)
|
||||||
z[i] = x[i] + 1.0f;
|
z[i] = x[i] + 1.0f;
|
||||||
|
|
||||||
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -676,8 +676,19 @@ propagate_necessity (struct edge_list *el)
|
||||||
|
|
||||||
if (is_gimple_call (stmt))
|
if (is_gimple_call (stmt))
|
||||||
{
|
{
|
||||||
|
tree callee = gimple_call_fndecl (stmt);
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
/* Calls to functions that are merely acting as barriers
|
||||||
|
or that only store to memory do not make any previous
|
||||||
|
stores necessary. */
|
||||||
|
if (callee != NULL_TREE
|
||||||
|
&& DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
|
||||||
|
&& (DECL_FUNCTION_CODE (callee) == BUILT_IN_MEMSET
|
||||||
|
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_MALLOC
|
||||||
|
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE))
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Calls implicitly load from memory, their arguments
|
/* Calls implicitly load from memory, their arguments
|
||||||
in addition may explicitly perform memory loads. */
|
in addition may explicitly perform memory loads. */
|
||||||
mark_all_reaching_defs_necessary (stmt);
|
mark_all_reaching_defs_necessary (stmt);
|
||||||
|
|
|
@ -3473,7 +3473,9 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
|
||||||
{
|
{
|
||||||
varinfo_t vi;
|
varinfo_t vi;
|
||||||
vi = make_constraint_from_heapvar (get_vi_for_tree (lhs), "HEAP");
|
vi = make_constraint_from_heapvar (get_vi_for_tree (lhs), "HEAP");
|
||||||
make_copy_constraint (vi, nonlocal_id);
|
/* We delay marking allocated storage global until we know if
|
||||||
|
it escapes. */
|
||||||
|
vi->is_global_var = 0;
|
||||||
}
|
}
|
||||||
else if (VEC_length (ce_s, rhsc) > 0)
|
else if (VEC_length (ce_s, rhsc) > 0)
|
||||||
{
|
{
|
||||||
|
@ -3910,6 +3912,13 @@ find_func_aliases (gimple origt)
|
||||||
{
|
{
|
||||||
make_escape_constraint (gimple_assign_rhs1 (t));
|
make_escape_constraint (gimple_assign_rhs1 (t));
|
||||||
}
|
}
|
||||||
|
/* Handle escapes through return. */
|
||||||
|
else if (gimple_code (t) == GIMPLE_RETURN
|
||||||
|
&& gimple_return_retval (t) != NULL_TREE
|
||||||
|
&& could_have_pointers (gimple_return_retval (t)))
|
||||||
|
{
|
||||||
|
make_escape_constraint (gimple_return_retval (t));
|
||||||
|
}
|
||||||
/* Handle asms conservatively by adding escape constraints to everything. */
|
/* Handle asms conservatively by adding escape constraints to everything. */
|
||||||
else if (gimple_code (t) == GIMPLE_ASM)
|
else if (gimple_code (t) == GIMPLE_ASM)
|
||||||
{
|
{
|
||||||
|
@ -5350,6 +5359,7 @@ compute_points_to_sets (void)
|
||||||
struct scc_info *si;
|
struct scc_info *si;
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
varinfo_t vi;
|
||||||
|
|
||||||
timevar_push (TV_TREE_PTA);
|
timevar_push (TV_TREE_PTA);
|
||||||
|
|
||||||
|
@ -5447,6 +5457,13 @@ compute_points_to_sets (void)
|
||||||
points-to solution queries. */
|
points-to solution queries. */
|
||||||
cfun->gimple_df->escaped.escaped = 0;
|
cfun->gimple_df->escaped.escaped = 0;
|
||||||
|
|
||||||
|
/* Mark escaped HEAP variables as global. */
|
||||||
|
for (i = 0; VEC_iterate (varinfo_t, varmap, i, vi); ++i)
|
||||||
|
if (vi->is_heap_var
|
||||||
|
&& !vi->is_global_var)
|
||||||
|
vi->is_global_var = pt_solution_includes (&cfun->gimple_df->escaped,
|
||||||
|
vi->decl);
|
||||||
|
|
||||||
/* Compute the points-to sets for pointer SSA_NAMEs. */
|
/* Compute the points-to sets for pointer SSA_NAMEs. */
|
||||||
for (i = 0; i < num_ssa_names; ++i)
|
for (i = 0; i < num_ssa_names; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
2009-07-01 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/19831
|
||||||
|
* testsuite/libmudflap.c/fail11-frag.c: Make allocated memory
|
||||||
|
escape.
|
||||||
|
* testsuite/libmudflap.c/fail12-frag.c: Likewise.
|
||||||
|
* testsuite/libmudflap.c/fail16-frag.c: Likewise.
|
||||||
|
* testsuite/libmudflap.c/fail31-frag.c: Likewise.
|
||||||
|
|
||||||
2009-06-30 Richard Sandiford <r.sandiford@uk.ibm.com>
|
2009-06-30 Richard Sandiford <r.sandiford@uk.ibm.com>
|
||||||
|
|
||||||
* testsuite/lib/libmudflap.exp (libmudflap-init): Don't add "."
|
* testsuite/lib/libmudflap.exp (libmudflap-init): Don't add "."
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
char *y;
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
int i = 10;
|
int i = 10;
|
||||||
char *x = (char *) malloc (i * sizeof (char));
|
char *x = (char *) malloc (i * sizeof (char));
|
||||||
|
y = x;
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
++x;
|
++x;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
int *y;
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
int i = 10;
|
int i = 10;
|
||||||
int *x = (int *) malloc (i * sizeof (int));
|
int *x = (int *) malloc (i * sizeof (int));
|
||||||
|
y = x;
|
||||||
while (i--)
|
while (i--)
|
||||||
{
|
{
|
||||||
++x;
|
++x;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
void *p;
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
struct base {
|
struct base {
|
||||||
|
@ -15,7 +16,7 @@ struct derived {
|
||||||
struct base *bp;
|
struct base *bp;
|
||||||
|
|
||||||
bp = (struct base *) malloc (sizeof (struct base));;
|
bp = (struct base *) malloc (sizeof (struct base));;
|
||||||
|
p = bp;
|
||||||
bp->basic = 10;
|
bp->basic = 10;
|
||||||
((struct derived *)bp)->extra = 'x';
|
((struct derived *)bp)->extra = 'x';
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -8,11 +8,12 @@ int main ()
|
||||||
int z = h (4, 10);
|
int z = h (4, 10);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int *p;
|
||||||
int h (int i, int j)
|
int h (int i, int j)
|
||||||
{
|
{
|
||||||
int k[i];
|
int k[i];
|
||||||
k[j] = i;
|
k[j] = i;
|
||||||
|
p = k;
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue