Commit 14c41b9b by Richard Guenther Committed by Richard Biener

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
parent f6e0880a
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
......
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
......
/* { 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 ...@@ -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) ...@@ -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" } } */
/* { 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 ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)
{ {
......
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 "."
......
#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;
......
#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;
......
#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 { ...@@ -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 () ...@@ -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;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment