diff mbox series

[committed] d: Fix ICE on named continue label in an unrolled loop [PR107592]

Message ID 20221130171314.323962-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Fix ICE on named continue label in an unrolled loop [PR107592] | expand

Commit Message

Iain Buclaw Nov. 30, 2022, 5:13 p.m. UTC
Hi,

This patch fixes an ICE with using `continue' on a named label in an
unrolled loop statement.

Continue labels in an unrolled loop require a unique label per
iteration.  Previously this used the Statement body node for each
unrolled iteration to generate a new entry in the label hash table.
This does not work when the continue label has an identifier, as said
named label is pointing to the outer UnrolledLoopStatement node.

What would happen is that during the lowering of `continue label', an
automatic label associated with the unrolled loop would be generated,
and a jump to that label inserted, but because it was never pushed by
the visitor for the loop itself, it subsequently never gets emitted.

To fix, correctly use the UnrolledLoopStatement as the key to look up
and store the break/continue label pair, but remove the continue label
from the value entry after every loop to force a new label to be
generated by the next call to `push_continue_label'

Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and
committed to mainline, and backported to previous release branches.

Regards
Iain.

---
	PR d/107592

gcc/d/ChangeLog:

	* toir.cc (IRVisitor::push_unrolled_continue_label): New method.
	(IRVisitor::pop_unrolled_continue_label): New method.
	(IRVisitor::visit (UnrolledLoopStatement *)): Use them instead of
	push_continue_label and pop_continue_label.

gcc/testsuite/ChangeLog:

	* gdc.dg/pr107592.d: New test.
---
 gcc/d/toir.cc                   | 26 ++++++++++++++++++++++++--
 gcc/testsuite/gdc.dg/pr107592.d | 13 +++++++++++++
 2 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/pr107592.d
diff mbox series

Patch

diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index e5f5751f6db..e387f27760d 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -529,6 +529,28 @@  public:
     this->do_label (label);
   }
 
+  /* Generate and set a new continue label for the current unrolled loop.  */
+
+  void push_unrolled_continue_label (UnrolledLoopStatement *s)
+  {
+    this->push_continue_label (s);
+  }
+
+  /* Finish with the continue label for the unrolled loop.  */
+
+  void pop_unrolled_continue_label (UnrolledLoopStatement *s)
+  {
+    Statement *stmt = s->getRelatedLabeled ();
+    d_label_entry *ent = d_function_chain->labels->get (stmt);
+    gcc_assert (ent != NULL && ent->bc_label == true);
+
+    this->pop_continue_label (TREE_VEC_ELT (ent->label, bc_continue));
+
+    /* Remove the continue label from the label htab, as a new one must be
+       inserted at the end of every unrolled loop.  */
+    ent->label = TREE_VEC_ELT (ent->label, bc_break);
+  }
+
   /* Visitor interfaces.  */
 
 
@@ -1089,9 +1111,9 @@  public:
 
 	if (statement != NULL)
 	  {
-	    tree lcontinue = this->push_continue_label (statement);
+	    this->push_unrolled_continue_label (s);
 	    this->build_stmt (statement);
-	    this->pop_continue_label (lcontinue);
+	    this->pop_unrolled_continue_label (s);
 	  }
       }
 
diff --git a/gcc/testsuite/gdc.dg/pr107592.d b/gcc/testsuite/gdc.dg/pr107592.d
new file mode 100644
index 00000000000..59f34477356
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr107592.d
@@ -0,0 +1,13 @@ 
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107592
+// { dg-do compile }
+
+void test107592(Things...)(Things things)
+{
+    label:
+    foreach (thing; things)
+    {
+        continue label;
+    }
+}
+
+alias a107592 = test107592!(string);