Search for reachable conditions without limiting the search to the nodes
dominated by the left-most term in the expression. Right operands are
conceptually still always dominated by the left-most term, but in
arbitrary programs there may be complex edges that breaks this.

As it turns out, it is not necessary to limit search by the dominator,
and it effectively only served as an optimization.

A new test case has been added with the code that triggered the bug.

gcc/ChangeLog:

        * tree-profile.cc (masking_vectors): Tweak comment.
        (cond_reachable_from): Remove dominated_by_p check.

gcc/testsuite/ChangeLog:

        * gcc.misc-tests/gcov-22.c: New test.
---
 gcc/testsuite/gcc.misc-tests/gcov-22.c | 40 ++++++++++++++++++++++++++
 gcc/tree-profile.cc                    | 15 +++-------
 2 files changed, 44 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.misc-tests/gcov-22.c

diff --git a/gcc/testsuite/gcc.misc-tests/gcov-22.c 
b/gcc/testsuite/gcc.misc-tests/gcov-22.c
new file mode 100644
index 00000000000..8aa8867dbf1
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/gcov-22.c
@@ -0,0 +1,40 @@
+/* { dg-options "-fprofile-conditions -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+#include <setjmp.h>
+jmp_buf buf;
+
+void noop() {}
+
+/* This function is a test to verify that the expression isolation does not
+   break on a CFG with the right set of complex edges.  The (_ && setjmp)
+   created complex edges after the function calls and a circular pair of
+   complex edges around the setjmp call.  This triggered a bug when the search
+   for right operands only would consider nodes dominated by the left-most
+   term, as this would only be the case if the complex edges were removed.
+
+   __builtin_setjmp did not trigger this, so we need setjmp from libc.  */
+void
+pathological001 (int a, int b, int c)
+{
+    if (a)  /* conditions(1/2) true(0) */
+               /* conditions(end) */
+       noop ();
+
+    if (b)  /* conditions(1/2) false(0) */
+               /* conditions(end) */
+       noop ();
+
+    if (c && setjmp (buf))  /* conditions(1/4) true(0 1) false(1) */
+                                       /* conditions(end) */
+       noop ();
+}
+
+int
+main ()
+{
+    pathological001 (0, 1, 0);
+}
+
+
+/* { dg-final { run-gcov conditions { --conditions gcov-22.c } } } */
diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
index c8b917afb9a..adab0f59c07 100644
--- a/gcc/tree-profile.cc
+++ b/gcc/tree-profile.cc
@@ -619,10 +619,10 @@ masking_vectors (conds_ctx& ctx, array_slice<basic_block> 
blocks,
 }
 
 /* Find the nodes reachable from p by following only (possibly contracted)
-   condition edges dominated by p and ignore DFS back edges.  From a high level
-   this is partitioning the CFG into subgraphs by removing all non-condition
-   edges and selecting a single connected subgraph.  This creates a cut C = (G,
-   G') where G is the returned explicitly by this function.
+   condition edges and ignoring DFS back edges.  From a high level this is
+   partitioning the CFG into subgraphs by removing all non-condition edges and
+   selecting a single connected subgraph.  This creates a cut C = (G, G') where
+   G is the returned explicitly by this function.
 
    It is assumed that all paths from p go through q (q post-dominates p).  p
    must always be the first term in an expression and a condition node.
@@ -631,11 +631,6 @@ masking_vectors (conds_ctx& ctx, array_slice<basic_block> 
blocks,
    this is a multi-term expression or the first block in the then/else block is
    a conditional expression as well.
 
-   Only nodes dominated by p is added - under optimization some blocks may be
-   merged and multiple independent conditions may share the same outcome
-   (making successors misidentified as a right operands), but true right-hand
-   operands are always dominated by the first term.
-
    The function outputs both a bitmap and a vector as both are useful to the
    caller.  */
 void
@@ -651,8 +646,6 @@ cond_reachable_from (basic_block p, basic_block q, sbitmap 
expr,
            basic_block dest = contract_edge (e)->dest;
            if (dest == q)
                continue;
-           if (!dominated_by_p (CDI_DOMINATORS, dest, p))
-               continue;
            if (!block_conditional_p (dest))
                continue;
            if (bitmap_bit_p (expr, dest->index))
-- 
2.30.2

Reply via email to