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 <mli...@suse.cz> 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 <mli...@suse.cz> 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 <mli...@suse.cz> 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