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

Reply via email to