aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-02-09 01:07:11 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-02-09 01:07:11 +0000
commit6d3aa24cd6535dcfc9f0701579eca53aa191768c (patch)
treef9732b16bca50b2d1c3b4ad86f5e65d8fe28c988 /gcc
parent7e64287b36bc9501cf8e214367b6d4dcfeeaae46 (diff)
downloadgcc-6d3aa24cd6535dcfc9f0701579eca53aa191768c.zip
gcc-6d3aa24cd6535dcfc9f0701579eca53aa191768c.tar.gz
gcc-6d3aa24cd6535dcfc9f0701579eca53aa191768c.tar.bz2
Fix ICE in find_taken_edge_computed_goto (PR 84136)
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. 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. From-SVN: r257509
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr84136.c15
-rw-r--r--gcc/tree-cfg.c12
4 files changed, 34 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dd78a34..8212952 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2018-02-08 David Malcolm <dmalcolm@redhat.com>
+
+ PR tree-optimization/84136
+ * tree-cfg.c (find_taken_edge_computed_goto): Remove assertion
+ that the result of find_edge is non-NULL.
+
2018-02-08 Sergey Shalnov <sergey.shalnov@intel.com>
PR target/83008
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d9ed50c..dfa8cb8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-02-08 David Malcolm <dmalcolm@redhat.com>
+
+ PR tree-optimization/84136
+ * gcc.c-torture/compile/pr84136.c: New test.
+
2018-02-08 Sergey Shalnov <sergey.shalnov@intel.com>
PR target/83008
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..b87e48d 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2379,10 +2379,14 @@ 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);
+
+ /* It's possible for find_edge to return NULL here on invalid code
+ that abuses the labels-as-values extension (e.g. code that attempts to
+ jump *between* functions via stored labels-as-values; PR 84136).
+ If so, then we simply return that NULL for the edge.
+ We don't currently have a way of detecting such invalid code, so we
+ can't assert that it was the case when a NULL edge occurs here. */
return e;
}