diff options
author | Richard Guenther <rguenther@suse.de> | 2011-09-08 13:00:23 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2011-09-08 13:00:23 +0000 |
commit | 996e1de5e6bced0c6b6b0cbacee11ccc720ccdf4 (patch) | |
tree | bcaff4692c5de5b68874b434da9ce5fdf5834598 /gcc | |
parent | c22c0db26ad16673415d7523781fcf80c8e545ba (diff) | |
download | gcc-996e1de5e6bced0c6b6b0cbacee11ccc720ccdf4.tar.gz |
re PR tree-optimization/19831 (Missing DSE/malloc/free optimization)
2011-09-08 Richard Guenther <rguenther@suse.de>
PR tree-optimization/19831
* tree-ssa-dce.c (mark_all_reaching_defs_necessary_1): Also
skip builtins with vdefs that do not really store something.
(propagate_necessity): For calls to free that we can associate
with an allocation function do not mark the freed pointer
definition necessary.
(eliminate_unnecessary_stmts): Remove a call to free if
the associated call to an allocation function is not necessary.
* gcc.dg/tree-ssa/pr19831-1.c: New testcase.
* gcc.dg/tree-ssa/pr19831-2.c: Likewise.
* gcc.dg/tree-ssa/pr19831-3.c: Likewise.
* gcc.dg/errno-1.c: Adjust.
From-SVN: r178687
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/errno-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr19831-1.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c | 39 | ||||
-rw-r--r-- | gcc/tree-ssa-dce.c | 63 |
7 files changed, 169 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f4416030d23..561c3dbecc1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,17 @@ 2011-09-08 Richard Guenther <rguenther@suse.de> PR tree-optimization/19831 + * tree-ssa-dce.c (mark_all_reaching_defs_necessary_1): Also + skip builtins with vdefs that do not really store something. + (propagate_necessity): For calls to free that we can associate + with an allocation function do not mark the freed pointer + definition necessary. + (eliminate_unnecessary_stmts): Remove a call to free if + the associated call to an allocation function is not necessary. + +2011-09-08 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/19831 * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Do not mark allocation functions as necessary. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b432683ced9..c6109a6e525 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,14 @@ 2011-09-08 Richard Guenther <rguenther@suse.de> PR tree-optimization/19831 + * gcc.dg/tree-ssa/pr19831-1.c: New testcase. + * gcc.dg/tree-ssa/pr19831-2.c: Likewise. + * gcc.dg/tree-ssa/pr19831-3.c: Likewise. + * gcc.dg/errno-1.c: Adjust. + +2011-09-08 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/19831 * gcc.dg/tree-ssa/ssa-dce-8.c: New testcase. 2011-09-08 Tobias Burnus <burnus@net-b.de> diff --git a/gcc/testsuite/gcc.dg/errno-1.c b/gcc/testsuite/gcc.dg/errno-1.c index d0365bed45b..295deefbe78 100644 --- a/gcc/testsuite/gcc.dg/errno-1.c +++ b/gcc/testsuite/gcc.dg/errno-1.c @@ -6,7 +6,7 @@ int main() { - void *p; + void * volatile p; errno = 0; p = malloc (-1); if (errno != 0) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-1.c new file mode 100644 index 00000000000..1c8f9722708 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-1.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +void test1(void) +{ + int *p = __builtin_malloc (sizeof (int) * 4); + int *q = p; + *q++ = 4; + *q++ = 4; + __builtin_free (p); +} + +void test3(int b) +{ + int *p = __builtin_malloc (sizeof (int) * 4); + if (b) + __builtin_free (p); + *p = 5; +} + +void test4(int b) +{ + int *p = __builtin_malloc (sizeof (int) * 4); + if (b) + __builtin_free (p); + *p = 5; + __builtin_free (p); +} + +/* { dg-final { scan-tree-dump-times "free" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "malloc" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c new file mode 100644 index 00000000000..bc7c4cc3182 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +void test1(void) +{ + int *p = __builtin_malloc (sizeof (int) * 4); + *p++ = 4; + __builtin_free (p); +} + +/* Undefined. We can't do anything here. */ + +/* { dg-final { scan-tree-dump-times "free" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "malloc" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c new file mode 100644 index 00000000000..02b55726a99 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void test2(void) +{ + int *p = __builtin_malloc (sizeof (int) * 4); + if (p == (void *)0) + __builtin_abort (); + __builtin_free (p); +} + +void test5(int b) +{ + int *p = __builtin_malloc (sizeof (int) * 4); + if (p) + __builtin_free (p); +} + +void test6(void) +{ + int *p = __builtin_malloc (sizeof (int) * 4); + if (p == (void *)0) + __builtin_abort (); + if (p) + __builtin_free (p); +} + +/* We should be able to remove all malloc/free pairs with CDDCE. + Assume p was non-NULL for test2. + For test5, it doesn't matter if p is NULL or non-NULL. */ + +/* { dg-final { scan-tree-dump-times "free" 0 "optimized" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "malloc" 0 "optimized" { xfail *-*-* } } } */ + +/* But make sure we don't partially optimize for now. */ + +/* { dg-final { scan-tree-dump-times "free" 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "malloc" 3 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index e29f3659be8..f225030de68 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -309,6 +309,8 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive) case BUILT_IN_CALLOC: case BUILT_IN_ALLOCA: return; + + default:; } /* Most, but not all function calls are required. Function calls that produce no result and have no side effects (i.e. const pure @@ -625,6 +627,25 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED, return false; } + /* We want to skip statments that do not constitute stores but have + a virtual definition. */ + if (is_gimple_call (def_stmt)) + { + tree callee = gimple_call_fndecl (def_stmt); + if (callee != NULL_TREE + && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) + switch (DECL_FUNCTION_CODE (callee)) + { + case BUILT_IN_MALLOC: + case BUILT_IN_CALLOC: + case BUILT_IN_ALLOCA: + case BUILT_IN_FREE: + return false; + + default:; + } + } + mark_operand_necessary (vdef); return false; @@ -805,6 +826,25 @@ propagate_necessity (struct edge_list *el) ssa_op_iter iter; tree use; + /* If this is a call to free which is directly fed by an + allocation function do not mark that necessary through + processing the argument. */ + if (gimple_call_builtin_p (stmt, BUILT_IN_FREE)) + { + tree ptr = gimple_call_arg (stmt, 0); + gimple def_stmt; + tree def_callee; + /* If the pointer we free is defined by an allocation + function do not add the call to the worklist. */ + if (TREE_CODE (ptr) == SSA_NAME + && is_gimple_call (def_stmt = SSA_NAME_DEF_STMT (ptr)) + && (def_callee = gimple_call_fndecl (def_stmt)) + && DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL + && (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC + || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC)) + continue; + } + FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) mark_operand_necessary (use); @@ -1218,6 +1258,29 @@ eliminate_unnecessary_stmts (void) stats.total++; + /* We can mark a call to free as not necessary if the + defining statement of its argument is an allocation + function and that is not necessary itself. */ + if (gimple_call_builtin_p (stmt, BUILT_IN_FREE)) + { + tree ptr = gimple_call_arg (stmt, 0); + tree callee2; + gimple def_stmt; + if (TREE_CODE (ptr) != SSA_NAME) + continue; + def_stmt = SSA_NAME_DEF_STMT (ptr); + if (!is_gimple_call (def_stmt) + || gimple_plf (def_stmt, STMT_NECESSARY)) + continue; + callee2 = gimple_call_fndecl (def_stmt); + if (callee2 == NULL_TREE + || DECL_BUILT_IN_CLASS (callee2) != BUILT_IN_NORMAL + || (DECL_FUNCTION_CODE (callee2) != BUILT_IN_MALLOC + && DECL_FUNCTION_CODE (callee2) != BUILT_IN_CALLOC)) + continue; + gimple_set_plf (stmt, STMT_NECESSARY, false); + } + /* If GSI is not necessary then remove it. */ if (!gimple_plf (stmt, STMT_NECESSARY)) { |