public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH/RFC] Fix ICE in find_taken_edge_computed_goto (PR 84136)
@ 2018-01-31 16:03 David Malcolm
  2018-01-31 17:45 ` Martin Sebor
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: David Malcolm @ 2018-01-31 16:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

PR 84136 reports an ICE within sccvn_dom_walker when handling a
C/C++ source file that overuses the labels-as-values extension.
The code in question stores a jump label into a global, and then
jumps to it from another function, which ICEs after inlining:

void* a;

void foo() {
  if ((a = &&l))
      return;

  l:;
}

int main() {
  foo();
  goto *a;

  return 0;
}

This appears to be far beyond what we claim to support in this
extension - but we shouldn't ICE.

What's happening is that, after inlining, we have usage of a *copy*
of the label, which optimizes away the if-return logic, turning it
into an infinite loop.

On entry to the sccvn_dom_walker we have this gimple:

main ()
{
  void * a.0_1;

  <bb 2> [count: 0]:
  a = &l;

  <bb 3> [count: 0]:
l:
  a.0_1 = a;
  goto a.0_1;
}

and:
  edge taken = find_taken_edge (bb, vn_valueize (val));
reasonably valueizes the:
  goto a.0_1;
after the:
  a = &l;
  a.0_1 = a;
as if it were:
  goto *&l;

find_taken_edge_computed_goto then has:

2380	  dest = label_to_block (val);
2381	  if (dest)
2382	    {
2383	      e = find_edge (bb, dest);
2384	      gcc_assert (e != NULL);
2385	    }

which locates dest as a self-jump from block 3 back to itself.

However, the find_edge call returns NULL - it has a predecessor edge
from block 2, but no successor edges.

Hence the assertion fails and we ICE.

A successor edge from the computed goto could have been created by
make_edges if the label stmt had been in the function, but make_edges
only looks in the current function when handling computed gotos, and
the label only appeared after inlining.

The following patch removes the assertion, fixing the ICE.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.

If that's option (a), there could be some other approaches:

(b) convert the assertion into a warning/error/sorry, on the
    assumption that if we don't detect such an edge then the code is
    presumably abusing the labels-as-values feature
(c) have make_edges detect such a problematic computed goto (maybe
    converting make_edges_bb's return value to an enum and adding a 4th
    value - though it's not clear what to do then with it)
(d) detect this case on inlining and handle it somehow (e.g. adding
    edges for labels that have appeared since make_edges originally
    ran, for computed gotos that have no out-edges)
(e) do nothing, keeping the assertion, and accept that this is going
    to fail on a non-release build
(f) something else?

Of the above, (d) seems to me to be the most robust solution, but I
don't know how far we want to go "down the rabbit hole" of handling
such uses of labels-as-values (beyond not ICE-ing on them).

Thoughts?

gcc/testsuite/ChangeLog:
	PR tree-optimization/84136
	* gcc.c-torture/compile/pr84136.c: New test.

gcc/ChangeLog:
	PR tree-optimization/84136
	* tree-cfg.c (find_taken_edge_computed_goto): Remove assertion
	that the result of find_edge is non-NULL.
---
 gcc/testsuite/gcc.c-torture/compile/pr84136.c | 15 +++++++++++++++
 gcc/tree-cfg.c                                |  5 +----
 2 files changed, 16 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr84136.c

diff --git a/gcc/testsuite/gcc.c-torture/compile/pr84136.c b/gcc/testsuite/gcc.c-torture/compile/pr84136.c
new file mode 100644
index 0000000..0a70e4e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr84136.c
@@ -0,0 +1,15 @@
+void* a;
+
+void foo() {
+    if ((a = &&l))
+        return;
+
+    l:;
+}
+
+int main() {
+    foo();
+    goto *a;
+
+    return 0;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index c5318b9..6b89307 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2379,10 +2379,7 @@ find_taken_edge_computed_goto (basic_block bb, tree val)
 
   dest = label_to_block (val);
   if (dest)
-    {
-      e = find_edge (bb, dest);
-      gcc_assert (e != NULL);
-    }
+    e = find_edge (bb, dest);
 
   return e;
 }
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-02-08 17:22 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-31 16:03 [PATCH/RFC] Fix ICE in find_taken_edge_computed_goto (PR 84136) David Malcolm
2018-01-31 17:45 ` Martin Sebor
2018-02-01 11:05 ` Richard Biener
2018-02-02 21:35   ` David Malcolm
2018-02-08  5:04     ` Jeff Law
2018-02-08 14:31       ` Richard Biener
2018-02-08  5:03   ` Jeff Law
2018-02-08 17:22     ` Joseph Myers
2018-02-08  5:01 ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).