summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2011-09-08 13:00:23 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2011-09-08 13:00:23 +0000
commit996e1de5e6bced0c6b6b0cbacee11ccc720ccdf4 (patch)
treebcaff4692c5de5b68874b434da9ce5fdf5834598 /gcc
parentc22c0db26ad16673415d7523781fcf80c8e545ba (diff)
downloadgcc-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/ChangeLog11
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.dg/errno-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19831-1.c32
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19831-3.c39
-rw-r--r--gcc/tree-ssa-dce.c63
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))
{