Hi.
After playing with the test-case, I noticed that we don't want
to handle new/delete operators with a varying (SSA_NAME) as a second argument.
Considering following test-case:
$ cat /tmp/new.C
struct S {
S ();
~S();
};
int a = 123;
void fn1() {
S *s = new S[a];
delete[] s;
}
$ ./xg++ -B. /tmp/new.C -O2 -fdump-tree-gimple=/dev/stdout:
a.1_1 = a;
D.2341 = (sizetype) a.1_1;
if (D.2341 <= 9223372036854775800) goto <D.2342>; else goto <D.2343>;
<D.2342>:
iftmp.0 = D.2341 + 8;
goto <D.2344>;
<D.2343>:
iftmp.0 = 18446744073709551615;
<D.2344>:
D.2323 = operator new [] (iftmp.0);
MEM[(sizetype *)D.2323] = D.2341;
try
{
D.2324 = D.2323 + 8;
D.2325 = D.2324;
_2 = D.2341 + 18446744073709551615;
D.2326 = (long int) _2;
try
{
<D.2346>:
if (D.2326 < 0) goto <D.2338>; else goto <D.2347>;
<D.2347>:
S::S (D.2325);
D.2325 = D.2325 + 1;
D.2326 = D.2326 + -1;
goto <D.2346>;
<D.2338>:
}
catch
{
{
struct S * D.2336;
if (D.2324 != 0B) goto <D.2348>; else goto <D.2349>;
<D.2348>:
_3 = (sizetype) D.2326;
_4 = D.2341 - _3;
_5 = _4 + 18446744073709551615;
D.2336 = D.2324 + _5;
<D.2350>:
if (D.2336 == D.2324) goto <D.2351>; else goto <D.2352>;
<D.2352>:
D.2336 = D.2336 + 18446744073709551615;
S::~S (D.2336);
goto <D.2350>;
<D.2351>:
goto <D.2353>;
<D.2349>:
<D.2353>:
}
}
retval.2 = D.2324;
}
catch
{
if (D.2341 <= 9223372036854775800) goto <D.2355>; else goto <D.2356>;
<D.2355>:
iftmp.3 = D.2341 + 8;
goto <D.2357>;
<D.2356>:
iftmp.3 = 18446744073709551615;
<D.2357>:
operator delete [] (D.2323, iftmp.3);
}
s = D.2323 + 8;
{
struct S * D.2337;
if (s != 0B) goto <D.2358>; else goto <D.2359>;
<D.2358>:
try
{
_6 = s + 18446744073709551608;
_7 = *_6;
D.2337 = s + _7;
<D.2360>:
if (D.2337 == s) goto <D.2361>; else goto <D.2362>;
<D.2362>:
D.2337 = D.2337 + 18446744073709551615;
S::~S (D.2337);
goto <D.2360>;
<D.2361>:
}
finally
{
_8 = s + 18446744073709551608;
_9 = *_8;
_10 = _9 + 8;
_11 = s + 18446744073709551608;
operator delete [] (_11, _10);
}
goto <D.2363>;
<D.2359>:
<D.2363>:
}
}
as seen from the dump, we first make a operator new[] for a capped value
based on variable 'a'. Latter we have a loop that calls S:S and catch block
contains another
loop calling S::~S. Similarly last part contains delete[] which is based on
number of really
allocated memory (that lives in *D.2323).
Anyway that's not a candidate for DCE. I'm testing following patch.
Martin
>From 312626229bfd4162550891bd8947b0fe310da6f5 Mon Sep 17 00:00:00 2001
From: Martin Liska <[email protected]>
Date: Tue, 30 Jul 2019 09:24:56 +0200
Subject: [PATCH] DCE: do not handle delete operators with a SSA_NAME as a size
argument (PR tree-optimization/91270).
gcc/ChangeLog:
2019-07-30 Martin Liska <[email protected]>
PR tree-optimization/91270
* tree-ssa-dce.c (simple_delete_operator_p): New.
(propagate_necessity): Use it to filter delete operators
that we want to delete.
(eliminate_unnecessary_stmts): Likewise.
gcc/testsuite/ChangeLog:
2019-07-30 Martin Liska <[email protected]>
PR tree-optimization/91270
* g++.dg/torture/pr91270.C: New test.
---
gcc/testsuite/g++.dg/torture/pr91270.C | 10 ++++++++++
gcc/tree-ssa-dce.c | 19 ++++++++++++++-----
2 files changed, 24 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/torture/pr91270.C
diff --git a/gcc/testsuite/g++.dg/torture/pr91270.C b/gcc/testsuite/g++.dg/torture/pr91270.C
new file mode 100644
index 00000000000..60d766e9e9f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr91270.C
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+struct S {
+ ~S();
+};
+int a = 123;
+void fn1() {
+ S *s = new S[a];
+ delete[] s;
+}
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 763b76f0e53..e844824dc12 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -646,6 +646,18 @@ degenerate_phi_p (gimple *phi)
return true;
}
+/* Return true when a GIMPLE STMT is a delete call operator that
+ has either one argument or second argument is an integer constant. */
+
+static bool
+simple_delete_operator_p (gimple *stmt)
+{
+ return (is_gimple_call (stmt)
+ && (gimple_call_operator_delete_p (as_a <gcall *> (stmt))
+ && (gimple_call_num_args (stmt) == 1
+ || TREE_CODE (gimple_call_arg (stmt, 1)) == INTEGER_CST)));
+}
+
/* Propagate necessity using the operands of necessary statements.
Process the uses on each statement in the worklist, and add all
feeding statements which contribute to the calculation of this
@@ -805,9 +817,7 @@ propagate_necessity (bool aggressive)
allocation function do not mark that necessary through
processing the argument. */
if (gimple_call_builtin_p (stmt, BUILT_IN_FREE)
- || (is_gimple_call (stmt)
- && gimple_call_operator_delete_p (as_a <gcall *> (stmt))))
-
+ || simple_delete_operator_p (stmt))
{
tree ptr = gimple_call_arg (stmt, 0);
gimple *def_stmt;
@@ -1306,8 +1316,7 @@ eliminate_unnecessary_stmts (void)
(and thus is getting removed). */
if (gimple_plf (stmt, STMT_NECESSARY)
&& (gimple_call_builtin_p (stmt, BUILT_IN_FREE)
- || (is_gimple_call (stmt)
- && gimple_call_operator_delete_p (as_a <gcall *> (stmt)))))
+ || simple_delete_operator_p (stmt)))
{
tree ptr = gimple_call_arg (stmt, 0);
if (TREE_CODE (ptr) == SSA_NAME)
--
2.22.0