[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2020-03-04 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

Jakub Jelinek  changed:

   What|Removed |Added

   Target Milestone|8.4 |8.5

--- Comment #11 from Jakub Jelinek  ---
GCC 8.4.0 has been released, adjusting target milestone.

[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2019-11-22 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

--- Comment #10 from Jakub Jelinek  ---
With the above changes, the bug is now latent.

[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2019-11-21 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

--- Comment #9 from Jakub Jelinek  ---
Author: jakub
Date: Thu Nov 21 17:21:46 2019
New Revision: 278587

URL: https://gcc.gnu.org/viewcvs?rev=278587&root=gcc&view=rev
Log:
PR tree-optimization/91355
* tree-ssa-sink.c (select_best_block): Use >= rather than >
for early_bb scaled count with best_bb count comparison.

* g++.dg/torture/pr91355.C: New test.

Added:
branches/gcc-8-branch/gcc/testsuite/g++.dg/torture/pr91355.C
Modified:
branches/gcc-8-branch/gcc/ChangeLog
branches/gcc-8-branch/gcc/testsuite/ChangeLog
branches/gcc-8-branch/gcc/tree-ssa-sink.c

[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2019-11-21 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

--- Comment #8 from Jakub Jelinek  ---
Author: jakub
Date: Thu Nov 21 13:53:57 2019
New Revision: 278551

URL: https://gcc.gnu.org/viewcvs?rev=278551&root=gcc&view=rev
Log:
PR tree-optimization/91355
* tree-ssa-sink.c (select_best_block): Use >= rather than >
for early_bb scaled count with best_bb count comparison.

* g++.dg/torture/pr91355.C: New test.

Added:
branches/gcc-9-branch/gcc/testsuite/g++.dg/torture/pr91355.C
Modified:
branches/gcc-9-branch/gcc/ChangeLog
branches/gcc-9-branch/gcc/testsuite/ChangeLog
branches/gcc-9-branch/gcc/tree-ssa-sink.c

[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2019-11-21 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

--- Comment #7 from Jakub Jelinek  ---
Author: jakub
Date: Thu Nov 21 10:59:27 2019
New Revision: 278548

URL: https://gcc.gnu.org/viewcvs?rev=278548&root=gcc&view=rev
Log:
PR tree-optimization/91355
* tree-ssa-sink.c (select_best_block): Use >= rather than >
for early_bb scaled count with best_bb count comparison.

* g++.dg/torture/pr91355.C: New test.

Added:
trunk/gcc/testsuite/g++.dg/torture/pr91355.C
Modified:
trunk/gcc/ChangeLog
trunk/gcc/testsuite/ChangeLog
trunk/gcc/tree-ssa-sink.c

[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2019-11-20 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

--- Comment #6 from Jakub Jelinek  ---
I think we have two issues.  One is that if we sink something on the edge
between resx and corresponding landing pad, ehcleanup2 is upset, and the other
one is that it is really not beneficial to sink the stmts there.  If we fix the
latter, we'd just have a latent bug though.

In the testcase, both best_bb (the bb from splitting the EH edge) as well as
early_bb have count of 0, because this is all EH stuff and happens only if the
code throws (which is always, but we handle EH as something very rare).
r254698 changed best_bb->count.to_frequency < early_bb->count.to_frequency *
82%
to !(best_bb->count.apply_scale(100,1) > early_bb->count.apply_scale(82,1))
and so with zero counts the condition was false, but now it is true.
Though, the comment talks about !(... >= ...) rather than !(... > ...).

Honza, shouldn't that be !(... >= ...) as the comment says?

At least for the case of zero counts, if early_bb has the same count as
best_bb, it isn't profitable to sink it, it should be profitable only if it has
82% smaller count (or smaller).

Changing the > into >= makes the wrong-code go away, though as I said, we have
a latent issue and from what I understood, PRE might be inserting on such edges
too, otherwise we wouldn't split it.

[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2019-11-20 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

Jakub Jelinek  changed:

   What|Removed |Added

 CC||ebotcazou at gcc dot gnu.org,
   ||rth at gcc dot gnu.org

--- Comment #5 from Jakub Jelinek  ---
I'm afraid I don't know enough of the EH rules on what's wrong, so will just
try to describe what happens:
;;   basic block 3, loop depth 0
;;pred:   2
  _10 = __cxa_allocate_exception (4);
  MEM[(int *)_10] = 3;
  __cxa_throw (_10, &_ZTIi, 0B);
;;succ:   6

;;   basic block 4, loop depth 0
;;pred:   2
  d.0_14 = d;
  _15 = d.0_14 + 1;
  d = _15;
  _6 = __cxa_allocate_exception (4);
  MEM[(int *)_6] = 3;
  __cxa_throw (_6, &_ZTIi, 0B);
;;succ:   5

;;   basic block 5, loop depth 0
;;pred:   4
:
  d.1_16 = d;
  _17 = d.1_16 + 4294967295;
  d = _17;
  resx 4
;;succ:   6

;;   basic block 6, loop depth 0
;;pred:   3
;;5
:
  _20 = __builtin_eh_filter (1);
  if (_20 == -1)
goto ; [0.00%]
  else
goto ; [0.00%]
;;succ:   8
;;7

Now, if not -fno-tree-sink or Honza's change is in, sink changes that to:
;;   basic block 5, loop depth 0, count 0 (precise), probably never executed
;;prev block 4, next block 10, flags: (NEW, REACHABLE, VISITED)
;;pred:   4 [never]  count:0 (precise) (EH,EXECUTABLE)
:
  resx 4
;;succ:   10 [never]  count:0 (precise) (EH,EXECUTABLE)

;;   basic block 10, loop depth 0, count 0 (precise), probably never executed
;;prev block 5, next block 9, flags: (NEW)
;;pred:   5 [never]  count:0 (precise) (EH,EXECUTABLE)
:
  d.1_16 = d;
  _17 = d.1_16 + 4294967295;
  d = _17;
  goto ; [100.00%]
;;succ:   6 [always]  count:0 (precise) (FALLTHRU)

;;   basic block 9, loop depth 0, count 0 (precise), probably never executed
;;prev block 10, next block 6, flags: (NEW)
;;pred:   3 [never]  count:0 (precise) (EH,EXECUTABLE)
:
;;succ:   6 [always]  count:0 (precise) (FALLTHRU)

;;   basic block 6, loop depth 0, count 0 (precise), probably never executed
;;prev block 9, next block 7, flags: (NEW, REACHABLE, VISITED)
;;pred:   9 [always]  count:0 (precise) (FALLTHRU)
;;10 [always]  count:0 (precise) (FALLTHRU)
:
  _20 = __builtin_eh_filter (1);
  if (_20 == -1)
goto ; [0.00%]
  else
goto ; [0.00%]
;;succ:   8 [never]  count:0 (precise) (TRUE_VALUE,EXECUTABLE)
;;7 [never]  count:0 (precise) (FALSE_VALUE,EXECUTABLE)

Before ehcleanup2 the difference is then (-fno-tree-sink -O1 vs. -ftree-sink
-O1):
 ;;   basic block 5, loop depth 0
 ;;pred:   4
 :
-  d.1_16 = d;
-  _17 = d.1_16 + 4294967295;
-  d = _17;
   resx 4
 ;;succ:   6

 ;;   basic block 6, loop depth 0
+;;pred:   5
+:
+  d.1_16 = d;
+  _17 = d.1_16 + 4294967295;
+  d = _17;
+  goto ; [100.00%]
+;;succ:   8
+
+;;   basic block 7, loop depth 0
 ;;pred:   3
-;;5
+:
+;;succ:   8
+
+;;   basic block 8, loop depth 0
+;;pred:   7
+;;6
 :
   _20 = __builtin_eh_filter (1);

Now, ehcleanup2 removes resx 4; for some reason:
 Before removal of unreachable regions:
 Eh tree:
-   1 allowed_exceptions land:{1,},{3,} filter :-1 types:int
+   1 allowed_exceptions land:{4,},{1,},{3,} filter :-1 types:int
  4 cleanup land:{2,}
 Reachable regions: n_bits = 8, set = {1 4 }
-Reachable landing pads: n_bits = 4, set = {1 2 }
+Reachable landing pads: n_bits = 5, set = {1 2 4 }
 Removing unreachable landing pad 3


 After removal of unreachable regions:
 Eh tree:
-   1 allowed_exceptions land:{1,} filter :-1 types:int
+   1 allowed_exceptions land:{4,},{1,} filter :-1 types:int
  4 cleanup land:{2,}


+Removing basic block 7
+Removing basic block 5
+Removing unreachable region 4
...
 ;;   basic block 5, loop depth 0
 ;;pred:   4
-:
+:
   d.1_16 = d;
   _17 = d.1_16 + 4294967295;
   d = _17;
-  resx 4
 ;;succ:   6

and in *.optimized dump that means:
 ;;   basic block 5, loop depth 0
 ;;pred:   4
-:
+:
   d.1_16 = d;
   _17 = d.1_16 + 4294967295;
   d = _17;
-  __builtin_eh_copy_values (1, 4);
 ;;succ:   6
change and abort.

[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2019-11-20 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

--- Comment #4 from Jakub Jelinek  ---
bb 10 into which it is sunk has been created by split_critical_edges, although
the edge from the resx 4; bb to the landing pad is not critical, there is:
  /* PRE inserts statements to edges and expects that
 since split_critical_edges was done beforehand, committing edge
 insertions will not split more edges.  In addition to critical
 edges we must split edges that have multiple successors and
 end by control flow statements, such as RESX.
 Go ahead and split them too.  This matches the logic in
 gimple_find_edge_insert_loc.  */

[Bug tree-optimization/91355] [8/9/10 Regression] optimized code does not call destructor while unwinding after exception

2019-11-20 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91355

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jakub at gcc dot gnu.org
  Component|c++ |tree-optimization

--- Comment #3 from Jakub Jelinek  ---
Slightly cleaned up testcase for g++.dg/torture/

// PR tree-optimization/91355
// { dg-do run { target c++14_down } }

unsigned int d = 0;

struct S {
  S () { d++; }
  S (const S &) { d++; }
  ~S () { d--; }
};

void
foo (int i) throw (int) // { dg-warning "dynamic exception specifications are
deprecated" "" { target c++11 } }
{
  if (i == 0)
throw 3;
  S d;
  throw 3;
}

int
main ()
{
  try { foo (1); } catch (...) {}
  if (d)
__builtin_abort ();
}

The sink pass first sinks d = d - 1; statements across resx 4; into a new basic
block which is made new successor of the bb containing resx 4;, so:
:
  d.1_16 = d;
  _17 = d.1_16 + 4294967295;
  d = _17;
  resx 4
becomes:
:
  resx 4

   [count: 0]:
:
  d.1_16 = d;
  _17 = d.1_16 + 4294967295;
  d = _17;
  goto ; [100.00%]

sink_code_in_bb has:
  /* We can't move things across abnormal edges, so don't try.  */
  FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & EDGE_ABNORMAL)
  goto earlyout;
Shouldn't that be & (EDGE_ABNORMAL | EDGE_EH) ?  Or are there any cases where
we actually want to sink something across EH edge?  Even if yes, we shouldn't
put anything before landing pads IMHO.