diff mbox

Fix PR middle-end/80707, ICE: r247844 causes error: extra outgoing edge

Message ID 6b6384fc-5280-f102-3066-1857620f2f7c@vnet.ibm.com
State New
Headers show

Commit Message

Peter Bergner May 12, 2017, 4:46 p.m. UTC
My fix for PR51513 modified group_case_labels_stmt() to remove unreachable
case statements labels.  Being a middle-end newbie, I incorrectly thought
group_case_labels_stmt() was only called very early, before we have a cfg.
With -O3, we can generate extra copies of the switch statement, well after
the cfg exists, and we end up calling group_case_labels_stmt() to optimize
them.  In those cases, we need to remove their edges from the cfg.

This passes my bootstrap and regtesting on powerpc64le-linux and x86_64-linux
with no regressions.  In addition, both David and HJ confirm this fixes the
bootstrap issues they ran into.

Is this ok for trunk?

Peter

gcc/
	PR middle-end/80707
	* tree-cfg.c: Remove cfg edges of unreachable case statements.

gcc/testsuite/
	* g++.dg/pr80707.C: New test.

Comments

Richard Biener May 12, 2017, 4:51 p.m. UTC | #1
On May 12, 2017 6:46:29 PM GMT+02:00, Peter Bergner <bergner@vnet.ibm.com> wrote:
>My fix for PR51513 modified group_case_labels_stmt() to remove
>unreachable
>case statements labels.  Being a middle-end newbie, I incorrectly
>thought
>group_case_labels_stmt() was only called very early, before we have a
>cfg.
>With -O3, we can generate extra copies of the switch statement, well
>after
>the cfg exists, and we end up calling group_case_labels_stmt() to
>optimize
>them.  In those cases, we need to remove their edges from the cfg.
>
>This passes my bootstrap and regtesting on powerpc64le-linux and
>x86_64-linux
>with no regressions.  In addition, both David and HJ confirm this fixes
>the
>bootstrap issues they ran into.
>
>Is this ok for trunk?

OK.

Richard.

>Peter
>
>gcc/
>	PR middle-end/80707
>	* tree-cfg.c: Remove cfg edges of unreachable case statements.
>
>gcc/testsuite/
>	* g++.dg/pr80707.C: New test.
>
>Index: gcc/tree-cfg.c
>===================================================================
>--- gcc/tree-cfg.c	(revision 247845)
>+++ gcc/tree-cfg.c	(working copy)
>@@ -1684,6 +1684,10 @@ group_case_labels_stmt (gswitch *stmt)
> 	  || (EDGE_COUNT (base_bb->succs) == 0
> 	      && gimple_seq_unreachable_p (bb_seq (base_bb))))
> 	{
>+	  edge e;
>+	  if (base_bb != default_bb
>+	      && (e = find_edge (gimple_bb (stmt), base_bb)) != NULL)
>+	    remove_edge_and_dominated_blocks (e);
> 	  gimple_switch_set_label (stmt, i, NULL_TREE);
> 	  i++;
> 	  new_size--;
>Index: gcc/testsuite/g++.dg/pr80707.C
>===================================================================
>--- gcc/testsuite/g++.dg/pr80707.C	(nonexistent)
>+++ gcc/testsuite/g++.dg/pr80707.C	(working copy)
>@@ -0,0 +1,29 @@
>+// PR middle-end/80707 ICE: extra outgoing edge causes
>verify_flow_info error.
>+// { dg-do compile }
>+// { dg-options "-O3" } */
>+
>+struct A {
>+  int m_fn1(int &) const;
>+};
>+int A::m_fn1(int &p1) const {
>+  int a[6];
>+  int b = 0;
>+  for (int i;; i++) {
>+    if (a[i])
>+      break;
>+    b++;
>+  }
>+  while (b) {
>+    int c;
>+    switch (b) {
>+    case 1:
>+      c = 0;
>+      break;
>+    case 5:
>+      c = a[0];
>+    }
>+    if (c)
>+      p1 = 0;
>+    b--;
>+  }
>+}
Peter Bergner May 12, 2017, 5:15 p.m. UTC | #2
On 5/12/17 11:51 AM, Richard Biener wrote:
> On May 12, 2017 6:46:29 PM GMT+02:00, Peter Bergner <bergner@vnet.ibm.com> wrote:>> gcc/
>> 	PR middle-end/80707
>> 	* tree-cfg.c: Remove cfg edges of unreachable case statements.
>>
>> gcc/testsuite/
>> 	* g++.dg/pr80707.C: New test.
>>
>> Is this ok for trunk?
> 
> OK.


Thanks, committed as revision 247984.

Peter
diff mbox

Patch

Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 247845)
+++ gcc/tree-cfg.c	(working copy)
@@ -1684,6 +1684,10 @@  group_case_labels_stmt (gswitch *stmt)
 	  || (EDGE_COUNT (base_bb->succs) == 0
 	      && gimple_seq_unreachable_p (bb_seq (base_bb))))
 	{
+	  edge e;
+	  if (base_bb != default_bb
+	      && (e = find_edge (gimple_bb (stmt), base_bb)) != NULL)
+	    remove_edge_and_dominated_blocks (e);
 	  gimple_switch_set_label (stmt, i, NULL_TREE);
 	  i++;
 	  new_size--;
Index: gcc/testsuite/g++.dg/pr80707.C
===================================================================
--- gcc/testsuite/g++.dg/pr80707.C	(nonexistent)
+++ gcc/testsuite/g++.dg/pr80707.C	(working copy)
@@ -0,0 +1,29 @@ 
+// PR middle-end/80707 ICE: extra outgoing edge causes verify_flow_info error.
+// { dg-do compile }
+// { dg-options "-O3" } */
+
+struct A {
+  int m_fn1(int &) const;
+};
+int A::m_fn1(int &p1) const {
+  int a[6];
+  int b = 0;
+  for (int i;; i++) {
+    if (a[i])
+      break;
+    b++;
+  }
+  while (b) {
+    int c;
+    switch (b) {
+    case 1:
+      c = 0;
+      break;
+    case 5:
+      c = a[0];
+    }
+    if (c)
+      p1 = 0;
+    b--;
+  }
+}